diff --git a/pkgs/applications/science/math/sage/patches/disable-pexpect-intermittent-failure.patch b/pkgs/applications/science/math/sage/patches/disable-pexpect-intermittent-failure.patch
new file mode 100644
index 000000000000..374c72079194
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/disable-pexpect-intermittent-failure.patch
@@ -0,0 +1,29 @@
+diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py
+index 88a33b0349..b3321f0bec 100644
+--- a/src/sage/interfaces/singular.py
++++ b/src/sage/interfaces/singular.py
+@@ -495,24 +495,6 @@ class Singular(ExtraTabCompletion, Expect):
+ """
+ Send an interrupt to Singular. If needed, additional
+ semi-colons are sent until we get back at the prompt.
+-
+- TESTS:
+-
+- The following works without restarting Singular::
+-
+- sage: a = singular(1)
+- sage: _ = singular._expect.sendline('1+') # unfinished input
+- sage: try:
+- ....: alarm(0.5)
+- ....: singular._expect_expr('>') # interrupt this
+- ....: except KeyboardInterrupt:
+- ....: pass
+- Control-C pressed. Interrupting Singular. Please wait a few seconds...
+-
+- We can still access a::
+-
+- sage: 2*a
+- 2
+ """
+ # Work around for Singular bug
+ # http://www.singular.uni-kl.de:8002/trac/ticket/727
diff --git a/pkgs/applications/science/math/sage/patches/dont-grep-threejs-version-from-minified-js.patch b/pkgs/applications/science/math/sage/patches/dont-grep-threejs-version-from-minified-js.patch
new file mode 100644
index 000000000000..88cb66506b1d
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/dont-grep-threejs-version-from-minified-js.patch
@@ -0,0 +1,16 @@
+diff --git a/src/sage/repl/rich_output/display_manager.py b/src/sage/repl/rich_output/display_manager.py
+index fb21f7a9c9..f39470777d 100644
+--- a/src/sage/repl/rich_output/display_manager.py
++++ b/src/sage/repl/rich_output/display_manager.py
+@@ -749,9 +749,9 @@ class DisplayManager(SageObject):
+ import sage.env
+ import re
+ import os
+- with open(os.path.join(sage.env.THREEJS_DIR, 'build', 'three.min.js')) as f:
++ with open(os.path.join(sage.env.THREEJS_DIR, 'build', 'three.js')) as f:
+ text = f.read().replace('\n','')
+- version = re.search(r'REVISION="(\d+)"', text).group(1)
++ version = re.search(r"REVISION = '(\d+)'", text).group(1)
+ return """
+
+
diff --git a/pkgs/applications/science/math/sage/sage-src.nix b/pkgs/applications/science/math/sage/sage-src.nix
index b8fb41596607..ff8e53d4172c 100644
--- a/pkgs/applications/science/math/sage/sage-src.nix
+++ b/pkgs/applications/science/math/sage/sage-src.nix
@@ -71,6 +71,9 @@ stdenv.mkDerivation rec {
# fix intermittent errors in sagespawn.pyx: https://trac.sagemath.org/ticket/31052
./patches/sagespawn-implicit-casting.patch
+
+ # disable pexpect interrupt test (see https://trac.sagemath.org/ticket/30945)
+ ./patches/disable-pexpect-intermittent-failure.patch
];
# Patches needed because of package updates. We could just pin the versions of
@@ -106,6 +109,9 @@ stdenv.mkDerivation rec {
# fix test output with sympy 1.7 (https://trac.sagemath.org/ticket/30985)
./patches/sympy-1.7-update.patch
+
+ # workaround until we use sage's fork of threejs, which contains a "version" file
+ ./patches/dont-grep-threejs-version-from-minified-js.patch
];
patches = nixPatches ++ bugfixPatches ++ packageUpgradePatches;