vscode调试erlang失败的主因是环境变量未正确继承,需确保which erl和which rebar3在内置终端中返回有效路径,并在设置中填写erlang.erlpath与erlang.rebar3path的绝对路径,重启后验证erlang-ls: ready状态。

VSCode 本身不运行 Erlang,它只调用你本地装好的 erl 和 rebar3;所有“点不动”“跳转灰”“调试失败”的问题,90% 是因为 erl 在 VSCode 内置终端里根本跑不起来——不是插件没装对,是环境没接上。
which erl 在 VSCode 终端里必须返回路径
这是整个配置的起点,也是最容易被跳过的验证步骤。按 Ctrl+` 打开内置终端,执行:
which erlwhich rebar3
任一命令返回空或 command not found,立刻停手,别配 launch.json,也别改插件设置。常见原因:
- 从桌面图标启动 VSCode → 它继承的是系统登录时的
PATH,不含你在~/.zshrc里加的 Erlang 路径 - Windows 上
erl.exe路径含中文或空格 → BEAM 启动失败,但错误只埋在语言服务器日志里,终端看不到 - 用
asdf管理版本 → 忘了运行asdf reshim erlang,which erl找不到软链接目标
修复方式只有一条:让 VSCode 继承正确的 PATH。要么在已配好环境的终端中执行 code . 启动 VSCode(推荐),要么把 Erlang bin 目录写进 ~/.zshrc(macOS/Linux)或系统环境变量(Windows),然后完全退出 VSCode 再重启。
erlang.erlPath 和 erlang.rebar3Path 必须填绝对路径
即使 which erl 有输出,erlang-ls 语言服务器默认也不读系统 PATH。它只认你在 VSCode 设置里显式填的两个路径——而且必须是真实可执行文件的绝对路径:
-
erlang.erlPath填/usr/local/lib/erlang/bin/erl(macOS/Linux)或C:\Program Files\erl-25.3\bin\erl.exe(Windows),不能是软链接、不能是erl.bat、也不能是目录 -
erlang.rebar3Path填/home/you/.local/bin/rebar3这类真实路径,不是rebar3.bat,也不是符号链接本身
改完后必须彻底重启 VSCode —— 语言服务器不会热重载。验证方式:打开任意 .erl 文件,右下角状态栏出现 erlang-ls: ready 才算生效。
tasks.json 必须基于 rebar3 编译
VSCode 的“运行”按钮不会自动编译 Erlang 项目。你得手动配置 tasks.json 把 rebar3 compile 接进来,否则改完代码直接调试,只会遇到未编译模块报错。示例最小可用配置:
{
"version": "2.0.0",
"tasks": [
{
"label": "rebar3 compile",
"type": "shell",
"command": "rebar3 compile",
"group": "build",
"problemMatcher": "$erlang"
}
]
}
注意点:
-
command必须是完整可执行命令,不要写成cd myapp && rebar3 compile—— 工作区路径由 VSCode 自动处理,硬写cd反而容易出错 -
problemMatcher设为"$erlang"才能正确解析编译错误并跳转到行号 - 如果项目结构多层嵌套(如 workspace 根目录下有多个 app),确保
rebar3当前工作目录是项目根目录(即含rebar.config的目录)
调试前必须手动验证 application:ensure_all_started/1
VSCode 调试器本质是启动一个带参数的 Erlang 节点再 attach,它不负责解决依赖缺失。如果你的 launch.json 里写的是 "startFun": "application:start", "startArgs": "[myapp]",但实际项目里 myapp 依赖 cowboy 而 cowboy 没 start,调试器会直接报 {error,{not_started,cowboy}} 并退出,连断点都设不上。
务必在调试前走通这三步:
- 在项目根目录运行
rebar3 shell - 在 shell 里执行
application:ensure_all_started(myapp).,确认返回ok - 检查
startFun是否匹配真实入口:有些项目用myapp:start/0,有些用myapp_app:start/2,函数签名错一个字符就失败
复杂点在于:application:ensure_all_started/1 成功不代表所有模块都已加载,某些模块可能延迟加载;断点只对已加载模块生效,首次调试建议先在 shell 里手动 c(my_module). 确保模块已编译并加载。











