{"record":{"id":"8931837bcd03384f","repo":"multica-ai/multica","slug":"config-must-be-valid-json-w","errorCode":null,"errorMessage":"--config must be valid JSON: %w","messagePattern":"--config must be valid JSON: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_skill.go","lineNumber":322,"sourceCode":"\n\tbody := map[string]any{\n\t\t\"name\": name,\n\t}\n\tif v, _ := cmd.Flags().GetString(\"description\"); v != \"\" {\n\t\tbody[\"description\"] = v\n\t}\n\tcontent, hasContent, err := resolveSkillContentFlag(cmd)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif hasContent && content != \"\" {\n\t\tbody[\"content\"] = content\n\t}\n\tif cmd.Flags().Changed(\"config\") {\n\t\tv, _ := cmd.Flags().GetString(\"config\")\n\t\tvar config any\n\t\tif err := json.Unmarshal([]byte(v), &config); err != nil {\n\t\t\treturn fmt.Errorf(\"--config must be valid JSON: %w\", err)\n\t\t}\n\t\tbody[\"config\"] = config\n\t}\n\n\tctx, cancel := cli.APIContext(context.Background())\n\tdefer cancel()\n\n\tvar result map[string]any\n\tif err := client.PostJSON(ctx, \"/api/skills\", body, &result); err != nil {\n\t\treturn fmt.Errorf(\"create skill: %w\", err)\n\t}\n\n\toutput, _ := cmd.Flags().GetString(\"output\")\n\tif output == \"json\" {\n\t\treturn cli.PrintJSON(os.Stdout, result)\n\t}\n\n\tfmt.Printf(\"Skill created: %s (%s)\\n\", strVal(result, \"name\"), strVal(result, \"id\"))","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_skill.go#L304-L340","documentation":"Validation of the --config flag in `multica skill create`: the flag fired (cmd.Flags().Changed) but its string value failed json.Unmarshal. The config must be a single valid JSON value (object recommended). The %w wraps the json error with position information. No API call is made.","triggerScenarios":"`multica skill create --name s --config '{\"max\":}'` (syntax error), single quotes lost through shell layering, or YAML/ini-style values passed where JSON is expected.","commonSituations":"Nested shell/ssh quoting stripping inner quotes; copy-pasting YAML from docs into --config; trailing commas; line breaks breaking the shell string.","solutions":["Validate locally first: `echo '<json>' | jq .` must succeed.","Prefer single-quoting the whole JSON and using double quotes inside, or --config \"$(jq -c . file.json)\" to build it safely.","For complex configs, keep a .json file and substitute with jq -c to guarantee compact valid JSON.","Check the wrapped json error's offset to find the syntax error position."],"exampleFix":"# before\nmultica skill create --name s --config \"{max: 3}\"\n# after\nmultica skill create --name s --config '{\"max\": 3}'","handlingStrategy":"validation","validationCode":"# Validate/normalize config before the CLI sees it\nCONFIG=$(jq -cn . <<<\"$RAW_CONFIG\") || { echo \"--config is not valid JSON\"; exit 2; }\nmultica skill create --name s --config \"$CONFIG\"","typeGuard":"function isValidJson(s: string): boolean {\n  try { JSON.parse(s); return true; } catch { return false; }\n}","tryCatchPattern":"On '--config must be valid JSON', feed the exact string to `jq .` or JSON.parse to locate the offset, fix quoting/syntax, and re-run — no server state was touched.","preventionTips":["Always round-trip --config values through jq -c.","Single-quote JSON for the shell, double quotes inside.","Watch for quoting loss through ssh/su/docker exec layers."],"tags":["go","cli","json","validation","shell-quoting","skills"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}