{"record":{"id":"2f84b584748d285b","repo":"multica-ai/multica","slug":"parse-cli-config-w","errorCode":null,"errorMessage":"parse CLI config: %w","messagePattern":"parse CLI config: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/cli/config.go","lineNumber":306,"sourceCode":"\treturn LoadCLIConfigForProfile(\"\")\n}\n\n// LoadCLIConfigForProfile reads the CLI config for the given profile.\nfunc LoadCLIConfigForProfile(profile string) (CLIConfig, error) {\n\tpath, err := CLIConfigPathForProfile(profile)\n\tif err != nil {\n\t\treturn CLIConfig{}, err\n\t}\n\tdata, err := os.ReadFile(path)\n\tif err != nil {\n\t\tif errors.Is(err, os.ErrNotExist) {\n\t\t\treturn CLIConfig{}, nil\n\t\t}\n\t\treturn CLIConfig{}, fmt.Errorf(\"read CLI config: %w\", err)\n\t}\n\tvar cfg CLIConfig\n\tif err := json.Unmarshal(data, &cfg); err != nil {\n\t\treturn CLIConfig{}, fmt.Errorf(\"parse CLI config: %w\", err)\n\t}\n\treturn cfg, nil\n}\n\n// SaveCLIConfig writes the CLI config to disk atomically (default profile).\nfunc SaveCLIConfig(cfg CLIConfig) error {\n\treturn SaveCLIConfigForProfile(cfg, \"\")\n}\n\n// SaveCLIConfigForProfile writes the CLI config for the given profile.\nfunc SaveCLIConfigForProfile(cfg CLIConfig, profile string) error {\n\tpath, err := CLIConfigPathForProfile(profile)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdir := filepath.Dir(path)\n\tdirMode := os.FileMode(0o755)\n\tif strings.TrimSpace(os.Getenv(TaskConfigRootEnv)) != \"\" {","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/cli/config.go#L288-L324","documentation":"The config file at the profile path was read successfully but json.Unmarshal could not decode it into CLIConfig. The wrapped error identifies the JSON syntax error and its byte offset. A missing file is treated as an empty config, so this only happens with present-but-invalid content.","triggerScenarios":"Calling LoadCLIConfig()/LoadCLIConfigForProfile when config.json contains truncated JSON (a crashed atomic write), hand-edited JSON with a trailing comma, or an object whose fields changed type between CLI versions.","commonSituations":"Editing ~/.multica/config.json by hand and introducing a syntax error; a killed process leaving a partially written file despite the temp-file rename; schema drift after upgrading the CLI to a version with different field types.","solutions":["Open the file named in the path resolution and fix the JSON syntax error indicated by the offset in the wrapped message","If the file is corrupt beyond repair, delete or rename it — the loader treats a missing file as a fresh empty config","Re-save a known-good config via the CLI's own config set/save command so future writes are atomic","If a field type changed after an upgrade, rewrite the values to match the current schema or start from the empty config"],"exampleFix":"// before: ~/.multica/profiles/dev/config.json\n{\"default_workspace\": \"acme\",}\n\n// after\n{\"default_workspace\": \"acme\"}","handlingStrategy":"validation","validationCode":"data, err := os.ReadFile(path)\nif err == nil {\n\tif !json.Valid(data) {\n\t\t// quarantine the bad file and start from an empty config\n\t\tos.Rename(path, path+\".invalid\")\n\t}\n}","typeGuard":"func isConfigParseErr(err error) bool {\n\tvar syn *json.SyntaxTypeError\n\treturn err != nil && (strings.Contains(err.Error(), \"parse CLI config:\") || errors.As(err, &syn))\n}","tryCatchPattern":"cfg, err := cli.LoadCLIConfigForProfile(profile)\nif err != nil {\n\tvar synErr *json.SyntaxError\n\tif errors.As(err, &synErr) {\n\t\t// offer to reset the config: delete the file so the next load is empty\n\t}\n\treturn err\n}","preventionTips":["Modify config only through the CLI's own set/save commands, which write atomically","Validate hand-edited JSON with jq before saving","Back up config.json before schema-changing upgrades"],"tags":["json","config","parsing","go"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}