sqlalchemy/alembic · error · OSError

No suitable editor found. Please set the "EDITOR" or…

Error message

No suitable editor found. Please set the "EDITOR" or "VISUAL" environment variables

What it means

Raised as OSError by _find_editor when neither the EDITOR nor VISUAL environment variables are set AND none of the default editor candidates (sensible-editor, editor, nano, vim, code on POSIX; code.exe, notepad++.exe, notepad.exe on Windows) are found on PATH (editor.py:48-55). Alembic needs an editor for 'alembic edit' and interactive 'alembic revision' commands.

Solutions

  1. Set the EDITOR environment variable: export EDITOR=vim (or nano, code, etc.).
  2. Install a common editor: apt-get install vim or apt-get install nano on Debian/Ubuntu.
  3. Set VISUAL as an alternative: export VISUAL=code.
  4. Use non-interactive mode to avoid the editor entirely: alembic revision -m 'description' instead of bare alembic revision.
  5. For containers, add 'ENV EDITOR=vim' to the Dockerfile or install an editor in the image.

Example fix

# before
alembic edit abc123  # OSError: No suitable editor found

# after
export EDITOR=vim
alembic edit abc123

# or skip the editor entirely
alembic revision -m 'add users table'
Defensive patterns

Strategy: validation

Validate before calling

import os
from os.path import exists

def ensure_editor_available(environ=None):
    env = environ or os.environ
    if 'EDITOR' in env or 'VISUAL' in env:
        return True
    from alembic.util.editor import _default_editors, _find_executable
    for candidate in _default_editors():
        if _find_executable(candidate, env) is not None:
            return True
    return False

Try / catch

from alembic.util.editor import _find_editor

try:
    editor = _find_editor(os.environ)
except OSError as e:
    if 'No suitable editor' in str(e):
        os.environ['EDITOR'] = 'vim'
        editor = _find_editor(os.environ)
    else:
        raise

Prevention

When it happens

Trigger: Calling alembic edit <revision> or alembic revision (without -m) on a system where no editor is configured. The loop at editor.py:48-51 tries each default candidate via _find_executable and all return None.

Common situations: Minimal Docker/container environments with no editor installed. CI environments running interactive commands. Fresh server installs without dev tools. SSH sessions where EDITOR isn't propagated. Windows systems without VS Code or Notepad++.

Related errors


AI-assisted analysis of sqlalchemy/alembic@5551b5d35f (2026-08-11). Data as JSON: /api/errors/4a0b7c806fb1a0dd. Report an issue: GitHub.

Appendix: source

Thrown at alembic/util/editor.py:52

    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 "
        '"EDITOR" or "VISUAL" environment variables'
    )


def _find_executable(candidate: str, environ: Mapping[str, str]) -> str | None:
    # Assuming this is on the PATH, we need to determine it's absolute
    # location. Otherwise, ``check_call`` will fail
    if not is_posix and splitext(candidate)[1] != ".exe":
        candidate += ".exe"
    for path in environ.get("PATH", "").split(os.pathsep):
        value = join(path, candidate)
        if exists(value):
            return value
    return None


def _default_editors() -> list[str]:

View on GitHub (pinned to 5551b5d35f)