sqlalchemy/alembic · error · CommandError
Error executing editor (%s)
Error message
Error executing editor (%s)
What it means
Raised as CommandError in open_in_editor (editor.py:35) wrapping ANY exception that escapes _find_editor or subprocess.check_call when launching the configured editor. It re-raises the original as __cause__ so the underlying failure (FileNotFoundError, non-zero editor exit, permission error) is preserved in the traceback.
Source
Thrown at alembic/util/editor.py:35
"""
Opens the given file in a text editor. If the environment variable
``EDITOR`` is set, this is taken as preference.
Otherwise, a list of commonly installed editors is tried.
If no editor matches, an :py:exc:`OSError` is raised.
:param filename: The filename to open. Will be passed verbatim to the
editor command.
:param environ: An optional drop-in replacement for ``os.environ``. Used
mainly for testing.
"""
env = os.environ if environ is None else environ
try:
editor = _find_editor(env)
check_call([editor, filename])
except Exception as exc:
raise CommandError("Error executing editor (%s)" % (exc,)) from exc
def _find_editor(environ: Mapping[str, str]) -> str:
candidates = _default_editors()
for i, var in enumerate(("EDITOR", "VISUAL")):
if var in environ:
user_choice = environ[var]
if exists(user_choice):
return user_choice
if os.sep not in user_choice:
candidates.insert(i, user_choice)
for candidate in candidates:
path = _find_executable(candidate, environ)
if path is not None:
return path
raise OSError(
"No suitable editor found. Please set the "View on GitHub (pinned to 44fb345033)
Solutions
- Check the wrapped exception (the '(FileNotFoundError ...)' or exit-code text) to see what actually failed.
- Set EDITOR to a blocking terminal editor (e.g. nano, vim) for non-GUI environments: `export EDITOR=nano`.
- Ensure an interactive TTY is available (run in a real terminal, not a detached CI shell) when invoking edit.
- Verify the migration file the editor was asked to open actually exists.
Example fix
# before: EDITOR points to a non-blocking GUI editor that exits immediately export EDITOR=code alembic edit abc123 # after: use a blocking editor export EDITOR=nano alembic edit abc123
Defensive patterns
Strategy: try-catch
Validate before calling
import os, shutil
def editor_is_callable() -> bool:
ed = os.environ.get('EDITOR') or os.environ.get('VISUAL')
return bool(ed and (os.path.exists(ed) or shutil.which(ed)))
if not editor_is_callable():
raise SystemExit('EDITOR not usable; set it before running alembic edit') Try / catch
from alembic.util.exc import CommandError
try:
command.edit(cfg, revision)
except CommandError as e:
if 'Error executing editor' in str(e):
print(f'Editor failed: {e.__cause__}. Set EDITOR to a blocking terminal editor.')
else:
raise Prevention
- Set EDITOR to a blocking, terminal-based editor in your shell profile.
- Ensure an interactive TTY is present when invoking alembic edit.
- For non-interactive scripts, avoid --edit and pass -m directly.
When it happens
Trigger: Running `alembic edit <revision>` or any code path that calls open_in_editor when the editor binary exists but fails to run, exits non-zero, or the target file path is invalid. The message interpolates the wrapped exception's repr.
Common situations: EDITOR set to a GUI editor (code, subl) that returns before the file is closed and Alembic reads it; editor exits non-zero due to a config problem; the migration file path passed to the editor is missing or unreadable; running in a container without an interactive TTY.
Related errors
- No suitable editor found. Please set the "EDITOR" or "VISUAL
- Template rendering failed; see %s for a template-oriented tr
- Can't drop table in batch mode
- Constraint must have a name
- No such constraint: '%s'
AI-assisted analysis of sqlalchemy/alembic@44fb345033 (2026-08-04).
Data as JSON: /data/errors/1df2bf42f5121016.json.
Report an issue: GitHub.