Summary
A single typo in Models.Roles.Main makes both netclaw doctor and netclaw doctor --fix crash with an unhandled exception and exit 134 (SIGABRT) — and netclaw model list explicitly directs the operator to run exactly those two commands. The diagnostic path is a dead end precisely when it is needed.
Repro
Verified against netclaw 0.25.0-alpha.onnx.7 (commit 5c7278f) in an isolated NETCLAW_HOME. Config is structurally valid and parses fine; Roles.Main just names a definition that doesn't exist:
{
"Providers": { "local": { "Type": "ollama", "BaseUrl": "http://localhost:11434" } },
"Models": {
"Definitions": { "local-qwen3-30b": { "Provider": "local", "ModelId": "qwen3:30b" } },
"Roles": { "Main": "does-not-exist" }
}
}
Step 1 — model list misdiagnoses and misdirects:
$ netclaw model list
Error: model configuration could not be parsed.
Run `netclaw doctor` to diagnose, or `netclaw doctor --fix` to repair it.
exit=1
The config did parse. The real error — Models:Roles:Main references unknown definition 'does-not-exist' — is produced by the resolver but caught and discarded at ModelCommand.cs:526-529.
Step 2 — the suggested command crashes:
$ netclaw doctor
Unhandled exception. System.InvalidOperationException: Models:Roles:Main references unknown definition 'does-not-exist'.
at Netclaw.Configuration.ModelConfigurationResolver.ResolveDefinition(...)
at Netclaw.Cli.Doctor.ContextWindowDoctorCheck.RunAsync(CancellationToken cancellationToken)
at Netclaw.Cli.Doctor.DoctorRunner.RunAsync(CancellationToken cancellationToken)
exit=134
Step 3 — so does the repair command, after printing a diff implying it will write:
$ netclaw doctor --fix -y
+ "Models": {
+ "Definitions": { ... },
+ "Roles": { "Main": "does-not-exist" }
+ },
+ }
Fatal error — crash log written to /home/petabridge/.netclaw/logs/crash-20260716-110953.log
Unhandled exception. System.InvalidOperationException: Models:Roles:Main references unknown definition 'does-not-exist'.
exit=134
Config is unchanged afterward. netclaw status is unaffected (exit 0).
Three distinct defects
- Wrong diagnosis.
model list reports "could not be parsed" for a config that parses. The accurate resolver message is swallowed at ModelCommand.cs:526-529.
- Wrong remediation. It points at
doctor --fix, which only converts legacy shape to named shape. It cannot repair an unresolved reference within an already-canonical config, so the advice would be wrong even if it ran.
- Crash instead of report.
ContextWindowDoctorCheck lets the resolver exception escape DoctorRunner. doctor is the tool of last resort for a broken config — it should be the one command that never dies on one.
Severity is amplified by the combination: the operator's only guidance leads to a core dump, with no message naming the offending role or definition.
Expected
model list surfaces the resolver's actual message (Models:Roles:Main references unknown definition 'does-not-exist'.).
doctor catches resolver failures and reports them as failed checks naming the role and the unknown definition.
- Remediation text points at fixing the reference (or lists valid definition names), not at
doctor --fix.
Test gap
Refresh_MissingNamedDefinition_SurfacesInvalidConfiguration (ModelManagerViewModelTests.cs:502) covers the TUI path only. There is no coverage for doctor or model list against an unresolved role reference.
Docs impact
netclaw-dev/netclaw-website#83 asks docs to state that model list reports unresolved config "with a clear error directing the operator to netclaw doctor / doctor --fix". That is not current behavior, and following it would send readers into a crash. Docs will document manual repair instead. Tracked in netclaw-dev/netclaw-website#86.
Summary
A single typo in
Models.Roles.Mainmakes bothnetclaw doctorandnetclaw doctor --fixcrash with an unhandled exception and exit 134 (SIGABRT) — andnetclaw model listexplicitly directs the operator to run exactly those two commands. The diagnostic path is a dead end precisely when it is needed.Repro
Verified against
netclaw 0.25.0-alpha.onnx.7 (commit 5c7278f)in an isolatedNETCLAW_HOME. Config is structurally valid and parses fine;Roles.Mainjust names a definition that doesn't exist:{ "Providers": { "local": { "Type": "ollama", "BaseUrl": "http://localhost:11434" } }, "Models": { "Definitions": { "local-qwen3-30b": { "Provider": "local", "ModelId": "qwen3:30b" } }, "Roles": { "Main": "does-not-exist" } } }Step 1 —
model listmisdiagnoses and misdirects:The config did parse. The real error —
Models:Roles:Main references unknown definition 'does-not-exist'— is produced by the resolver but caught and discarded atModelCommand.cs:526-529.Step 2 — the suggested command crashes:
Step 3 — so does the repair command, after printing a diff implying it will write:
Config is unchanged afterward.
netclaw statusis unaffected (exit 0).Three distinct defects
model listreports "could not be parsed" for a config that parses. The accurate resolver message is swallowed atModelCommand.cs:526-529.doctor --fix, which only converts legacy shape to named shape. It cannot repair an unresolved reference within an already-canonical config, so the advice would be wrong even if it ran.ContextWindowDoctorChecklets the resolver exception escapeDoctorRunner.doctoris the tool of last resort for a broken config — it should be the one command that never dies on one.Severity is amplified by the combination: the operator's only guidance leads to a core dump, with no message naming the offending role or definition.
Expected
model listsurfaces the resolver's actual message (Models:Roles:Main references unknown definition 'does-not-exist'.).doctorcatches resolver failures and reports them as failed checks naming the role and the unknown definition.doctor --fix.Test gap
Refresh_MissingNamedDefinition_SurfacesInvalidConfiguration(ModelManagerViewModelTests.cs:502) covers the TUI path only. There is no coverage fordoctorormodel listagainst an unresolved role reference.Docs impact
netclaw-dev/netclaw-website#83 asks docs to state that
model listreports unresolved config "with a clear error directing the operator tonetclaw doctor/doctor --fix". That is not current behavior, and following it would send readers into a crash. Docs will document manual repair instead. Tracked in netclaw-dev/netclaw-website#86.