Skip to content

model set / doctor --fix: legacy env-override migration guard throws unhandled exception instead of clean CLI error #1675

Description

@Aaronontheweb

Summary

The guard that blocks model-config migration while legacy NETCLAW_Models__Main__* environment overrides are present is correct in intent but surfaces as an unhandled exception — stack trace, crash log, and exit 134 (SIGABRT) instead of a clean CLI error.

Repro

Verified against netclaw 0.25.0-alpha.onnx.7 (commit 5c7278f) in an isolated NETCLAW_HOME.

Legacy-shape config:

{
  "Providers": { "local": { "Type": "ollama", "BaseUrl": "http://localhost:11434" } },
  "Models": { "Main": { "Provider": "local", "ModelId": "qwen3:30b" } }
}

Then:

$ export NETCLAW_Models__Main__ContextWindow="65536"
$ netclaw model set main local qwen3:8b

Fatal error — crash log written to /home/petabridge/.netclaw/logs/crash-20260716-110951.log
Unhandled exception. System.InvalidOperationException: Cannot migrate Models while legacy environment override 'NETCLAW_Models__Main__ContextWindow' is set. Move model overrides to NETCLAW_Models__Definitions__<name>__* and NETCLAW_Models__Roles__* first.
   at Netclaw.Cli.Config.ConfigFileHelper.PreserveLegacyModelsBackup(String path, Dictionary`2 data)
   at Netclaw.Cli.Config.ConfigFileHelper.WriteConfigFile(String path, Dictionary`2 data)
   at Netclaw.Cli.Model.ModelCommand.RunSetAsync(String[] args, NetclawPaths paths, IProviderProbe probe, TextWriter writer)
   ...
exit=134

Expected

The message itself is good — accurate, actionable, names the offending variable and the fix. It should print as Error: ... and exit 1, consistent with every other model set validation failure (unknown provider, invalid modalities, conflicting flags).

Cause

RunSetAsync has no try/catch around WriteConfigFile (ModelCommand.cs:283). The guard throws from ConfigFileHelper.cs:183-186 (and DoctorFixService.cs:73-76 on the doctor --fix path).

Correctness note

The guard works: config was not rewritten and no partial state was left behind. This is purely a presentation defect — but exit 134 + a crash log reads as "netclaw broke" rather than "your environment needs a change", and it pollutes the crash-log directory with entries that aren't crashes.

Aside (minor, possibly separate)

The crash log was written to /home/petabridge/.netclaw/logs/ even though NETCLAW_HOME pointed at a sandbox — crash logging appears not to respect NETCLAW_HOME. Noting here rather than filing separately; happy to split out.

Docs impact

netclaw-dev/netclaw-website#83 asks docs to cover the env-var migration guard. Docs will state the guard exists and quote the message, but cannot present it as a clean error path until this is fixed. Tracked in netclaw-dev/netclaw-website#86.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions