VSCode 仅通过 ElixirLS 提供语法支持,Ecto 迁移与查询实际由本地 Erlang 进程执行;配置失效根源在于终端环境与项目结构,需验证 PATH、版本管理器、mix.exs 应用声明、config 配置键名、Repo 模块路径及 OTP 应用生命周期。

VSCode 本身不执行 Ecto 迁移或查询,它只通过 ElixirLS 提供语法支持、跳转和错误提示;真正跑 mix ecto.migrate 或 Repo.insert/1 的是本地 Erlang 进程,配置失效的根源几乎都在终端环境与项目结构上。
mix ecto.* 命令在 VSCode 终端里根本跑不起来
这不是插件问题,而是 VSCode 集成终端没继承你 shell 的 PATH 或没加载正确的版本管理器环境。
- 必须在 VSCode 内置终端(
Ctrl+`)中逐个验证:which mix、which elixir、mix --version—— 全部要有输出,且版本号符合预期 - 用
asdf管理版本的,进项目目录后运行asdf current elixir和asdf current erlang,确认输出与mix --version一致 - Mac 用户常见坑:
/opt/homebrew/bin在$PATH里排太靠后,或~/.zshrc里没 source asdf 的 init 脚本,导致终端里能用、VSCode 里找不到命令 - Windows 用户注意:
mix.bat必须存在且可执行,PowerShell 默认禁用脚本执行策略,需先运行Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
Ecto 迁移文件生成后,mix ecto.migrate 报 “no repo configured”
这个错误说明 ElixirLS 能识别代码,但 runtime 根本没加载你的 Repo 模块——mix.exs 里没声明应用,或 config/config.exs 路径/键名写错。
- 检查
mix.exs的application: [...]列表是否包含你的Repo所在应用名,比如:my_app;否则mix ecto.migrate启动时不会加载 config -
config/config.exs中的配置 key 必须严格匹配:config :my_app, MyApp.Repo, ...—— 第一个原子是 app 名,第二个是模块全名,大小写、命名空间一个都不能错 - Repo 模块必须定义在
lib/my_app/repo.ex,且含use Ecto.Repo;如果用mix ecto.gen.repo生成过,别手动改模块名,否则 config 和模块对不上 - 迁移文件必须放在
priv/repo/migrations/下,文件名形如20260525123456_create_users.exs,时间戳不能重复,也不能手动生成空文件
Repo.insert/1 在 IEx 里成功,但在 VSCode 调试时抛出 DBConnection.OwnershipError
这是典型的连接池所有权冲突:ElixirLS 启动的调试进程默认不带数据库连接,而你在代码里直接调用了需要 Repo 的函数,却没显式指定上下文。
- 不要在模块顶层或
defmodule外直接写Repo.insert!—— 它会尝试在编译期执行,此时 Repo 尚未启动 - 调试时用
type: "mix_task"启动(如phx.server),确保整个应用 supervision tree 包括 Repo 已启动;若只调试单个函数,先在 IEx 里手动MyApp.Repo.start_link([]) - 查 ownership 错误时,看堆栈最顶上是不是
Ecto.Adapters.SQL.Sandbox.checkout/1—— 如果是,说明你启用了测试沙箱但没在测试配置里关掉,或忘记加@tag :capture_log等隔离标记 - VSCode 的 ElixirLS 调试器不自动接管 sandbox 行为,
mix test能过不代表调试器里能过;临时绕过方法:在调试前加:ok = Ecto.Adapters.SQL.Sandbox.checkout(MyApp.Repo)
最容易被忽略的是:Ecto 的所有行为都依赖 OTP 应用生命周期,VSCode 只是“看得到”,不是“管得了”。哪怕 mix ecto.migrate 成功了,如果 MyApp.Repo 没被加入 application 的 mod: {MyApp.Application, []},运行时照样连不上库。别只盯着代码高亮有没有红波浪线,先确保 mix compile 和 mix run -e 'IO.inspect(MyApp.Repo.config())' 都能安静跑完。


















