You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I entered an invalid ~/.config/opencode/opencode.json (or local opencode.json) and opencode started without complaining. This is important for new users (like me) who are trying to learn how to configure opencode. Mistakes are silently ignored.
The real issue for me is that my ollama provider in opencode.json is sometimes ignored, but without any indication of errors, how can I diagnose the configuration?
Plugins
No response
OpenCode version
v2.0.27
Steps to reproduce
Download standalone CLI binary from https://opencode.ai/v2/docs
I used x86, both glibc (with debian-13), and musl (with alpine 3.24.2).
create ~/.config/opencode/opencode.json with invalid JSON content. I used "{".
run "opencode models"
Result
A list of models from the opencode/ provider.
Expected result
An error indicating that opencode.json is invalid.
Thanks for the clear report, @melato. I can reproduce this.
With a clean config directory on v2.0.27 (Linux):
Put just { in ~/.config/opencode/opencode.json.
Run opencode models.
It lists the built-in opencode/* models, exits 0, and shows no error or warning. A malformed project ./opencode.json behaves the same way. The script below reproduces it.
It still happens on the latest dev (bcf23b6) with the global { case; I didn't run the project-file case there. From the code, the config loader notices the parse error but only writes it as a log warning and then skips the file. I couldn't find that warning in a log file during my test, so for now there's no reliable way to spot a rejected config. A file that parses but fails validation is also dropped without a message. That could explain why your Ollama provider is sometimes ignored: if part of the config is invalid, the whole file may be dropped.
Related: #54109 (custom Ollama provider ignored) and #53744 (provider dropped without a message because of a schema mismatch).
Reproduction script (repro.sh)
#!/usr/bin/env bash# Reproduces anomalyco/opencode#54786: an invalid opencode.json is silently ignored.# Usage: ./repro.sh (uses `opencode` from PATH)# OC_DEV=/path/to/repo ./repro.sh (runs the CLI from a source checkout)set -u
WORK=$(mktemp -d)export HOME="$WORK/home"export XDG_CONFIG_HOME="$HOME/.config" XDG_DATA_HOME="$HOME/.local/share" XDG_STATE_HOME="$HOME/.local/state" XDG_CACHE_HOME="$HOME/.cache"
mkdir -p "$XDG_CONFIG_HOME/opencode""$WORK/project"cd"$WORK/project"run() {
if [ -n"${OC_DEV:-}" ];then# run from packages/cli so its bunfig.toml (Solid JSX preload) also applies to the spawned server process
(cd "$OC_DEV/packages/cli"&& bun --conditions=browser src/index.ts "$@")
else
opencode "$@"fi
}
echo"== version: $(run --version 2>&1| tail -1)"echo'{'>"$XDG_CONFIG_HOME/opencode/opencode.json"echo"== Case 1: global opencode.json contains just '{'"
run models;echo"exit code: $?"
rm "$XDG_CONFIG_HOME/opencode/opencode.json"echo'{ "this is": not json'> opencode.json
if [ -n"${OC_DEV:-}" ];thenexit 0;fi# case 2 needs the project as cwdecho"== Case 2: project ./opencode.json is malformed"
run models;echo"exit code: $?"
I checked the real source CLI on bcf23b6 with isolated XDG directories and a private server (no model calls). models --standalone --print-logs makes the diagnostic visible:
{: warning with the config path, path=$, and rejected malformed JSON or JSONC document.
{"model":42}: warning at $.model, skipped malformed recognized value.
{}: no configuration warning.
Both warnings also reached $XDG_DATA_HOME/opencode/log/opencode-local.log. All three runs still exit 0 and list models, so this confirms a troubleshooting path, not a fix for the default silent UX. The existing source-aware/redaction and invalid-file controls also pass.
The CLI's --print-logs help explicitly says server logs require --standalone; printing only the client logs can miss this loader warning. AI-assisted investigation.
Reproduced on a source build of v2 (Windows): '{' as the entire global opencode.json -> models --standalone lists built-ins, exit 0, no error. Root cause looks like packages/core/src/config.ts: parseInfo logs a warning and returns undefined on malformed JSON, and loadFile then silently skips the file. I'd like to work on this - leaning toward failing startup with the file path and parse error rather than a log-only warning. Happy to do a surfaced warning instead if maintainers prefer.
Follow-up from digging into the loader: the silent skip looks intentional and pinned. packages/core/src/config.ts parseInfo/loadFile logs a configuration normalization diagnostic and skips the file, and packages/core/test/config/config.test.ts:690-781 feeds malformed global, project, explicit-file, wellknown, and OPENCODE_CONFIG_CONTENT sources while asserting load succeeds. So failing hard on invalid files would flip that tested contract. Two options: (a) fail startup with the file path and parse error (updating that test), or (b) keep loading and add a user-visible warning path (none exists today; logs need --print-logs --standalone). Which do maintainers prefer?
I reached the same conclusion that the silent skip is pinned by packages/core/test/config/config.test.ts:690. I went with option (b): the loader now keeps a rejected file as a Config.Rejected entry in /api/config and the CLI reports it on stderr before running, without changing the graceful-load contract. PR: #54804
Thank you! Yes, I went with your option (b) — the silent-skip contract pinned in config.test.ts stays intact, and rejected files now surface as Config.Rejected entries via /api/config plus a CLI stderr warning. A review would be very welcome, especially on the Rejected entry shape in the public API (packages/schema/src/config.ts) and the extra /api/config fetch in server-connection.ts. If you can re-run your Windows repro (malformed global config, models --standalone), that would be ideal — you should now see the warning on stderr instead of silence.
Activity
opencode-agent commentedon Oct 12, 2026
Thanks for the clear report, @melato. I can reproduce this.
With a clean config directory on v2.0.27 (Linux):
{in~/.config/opencode/opencode.json.opencode models.It lists the built-in
opencode/*models, exits 0, and shows no error or warning. A malformed project./opencode.jsonbehaves the same way. The script below reproduces it.It still happens on the latest
dev(bcf23b6) with the global{case; I didn't run the project-file case there. From the code, the config loader notices the parse error but only writes it as a log warning and then skips the file. I couldn't find that warning in a log file during my test, so for now there's no reliable way to spot a rejected config. A file that parses but fails validation is also dropped without a message. That could explain why your Ollama provider is sometimes ignored: if part of the config is invalid, the whole file may be dropped.Related: #54109 (custom Ollama provider ignored) and #53744 (provider dropped without a message because of a schema mismatch).
Reproduction script (repro.sh)
Run it:
bash repro.shr266-tech commentedon Oct 12, 2026
I checked the real source CLI on
bcf23b6with isolated XDG directories and a private server (no model calls).models --standalone --print-logsmakes the diagnostic visible:{: warning with the config path,path=$, andrejected malformed JSON or JSONC document.{"model":42}: warning at$.model,skipped malformed recognized value.{}: no configuration warning.Both warnings also reached
$XDG_DATA_HOME/opencode/log/opencode-local.log. All three runs still exit 0 and list models, so this confirms a troubleshooting path, not a fix for the default silent UX. The existing source-aware/redaction and invalid-file controls also pass.The CLI's
--print-logshelp explicitly says server logs require--standalone; printing only the client logs can miss this loader warning. AI-assisted investigation.Velmet44 commentedon Oct 12, 2026
Reproduced on a source build of v2 (Windows): '{' as the entire global opencode.json -> models --standalone lists built-ins, exit 0, no error. Root cause looks like packages/core/src/config.ts: parseInfo logs a warning and returns undefined on malformed JSON, and loadFile then silently skips the file. I'd like to work on this - leaning toward failing startup with the file path and parse error rather than a log-only warning. Happy to do a surfaced warning instead if maintainers prefer.
Velmet44 commentedon Oct 12, 2026
Follow-up from digging into the loader: the silent skip looks intentional and pinned. packages/core/src/config.ts parseInfo/loadFile logs a configuration normalization diagnostic and skips the file, and packages/core/test/config/config.test.ts:690-781 feeds malformed global, project, explicit-file, wellknown, and OPENCODE_CONFIG_CONTENT sources while asserting load succeeds. So failing hard on invalid files would flip that tested contract. Two options: (a) fail startup with the file path and parse error (updating that test), or (b) keep loading and add a user-visible warning path (none exists today; logs need --print-logs --standalone). Which do maintainers prefer?
reynold-hu commentedon Oct 12, 2026
I reached the same conclusion that the silent skip is pinned by packages/core/test/config/config.test.ts:690. I went with option (b): the loader now keeps a rejected file as a
Config.Rejectedentry in/api/configand the CLI reports it on stderr before running, without changing the graceful-load contract. PR: #54804Velmet44 commentedon Oct 15, 2026
reynold-hu's approach matches option (b) from my analysis above - standing down here. Happy to help review or test #54804 if useful.
reynold-hu commentedon Oct 16, 2026
Thank you! Yes, I went with your option (b) — the silent-skip contract pinned in
config.test.tsstays intact, and rejected files now surface asConfig.Rejectedentries via/api/configplus a CLI stderr warning. A review would be very welcome, especially on theRejectedentry shape in the public API (packages/schema/src/config.ts) and the extra/api/configfetch inserver-connection.ts. If you can re-run your Windows repro (malformed global config,models --standalone), that would be ideal — you should now see the warning on stderr instead of silence.