{"record":{"id":"e48e6a571e7842c2","repo":"caddyserver/caddy","slug":"config-is-not-valid-json-w-did-you-mean-to-use","errorCode":null,"errorMessage":"config is not valid JSON: %w; did you mean to use a config adapter (the --adapter flag)?","messagePattern":"config is not valid JSON: %w; did you mean to use a config adapter \\(the --adapter flag\\)\\?","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/main.go","lineNumber":237,"sourceCode":"\t\tfor _, warn := range warnings {\n\t\t\tmsg := warn.Message\n\t\t\tif warn.Directive != \"\" {\n\t\t\t\tmsg = fmt.Sprintf(\"%s: %s\", warn.Directive, warn.Message)\n\t\t\t}\n\t\t\tlogger.Warn(msg,\n\t\t\t\tzap.String(\"adapter\", adapterName),\n\t\t\t\tzap.String(\"file\", warn.File),\n\t\t\t\tzap.Int(\"line\", warn.Line))\n\t\t}\n\t\tconfig = adaptedConfig\n\t} else if len(config) != 0 {\n\t\t// validate that the config is at least valid JSON\n\t\terr = json.Unmarshal(config, new(any))\n\t\tif err != nil {\n\t\t\tif jsonErr, ok := err.(*json.SyntaxError); ok {\n\t\t\t\treturn nil, \"\", \"\", fmt.Errorf(\"config is not valid JSON: %w, at offset %d; did you mean to use a config adapter (the --adapter flag)?\", err, jsonErr.Offset)\n\t\t\t}\n\t\t\treturn nil, \"\", \"\", fmt.Errorf(\"config is not valid JSON: %w; did you mean to use a config adapter (the --adapter flag)?\", err)\n\t\t}\n\t}\n\n\treturn config, configFile, adapterName, nil\n}\n\n// watchConfigFile watches the config file at filename for changes\n// and reloads the config if the file was updated. This function\n// blocks indefinitely; it only quits if the poller has errors for\n// long enough time. The filename passed in must be the actual\n// config file used, not one to be discovered.\n// Each second the config files is loaded and parsed into an object\n// and is compared to the last config object that was loaded\nfunc watchConfigFile(filename, adapterName string) {\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\tlog.Printf(\"[PANIC] watching config file: %v\\n%s\", err, debug.Stack())\n\t\t}","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/cmd/main.go#L219-L255","documentation":"Same JSON validation gate as the offset variant, but the unmarshal error was not a *json.SyntaxError — typically *json.UnmarshalTypeError (right syntax, wrong type, e.g. a string where an object is required) or unexpected EOF on a truncated file. The --adapter hint is still appended because non-JSON input is a plausible cause.","triggerScenarios":"A JSON config where a field has the wrong shape (\"admin\": \"localhost:2019\" instead of an object); a truncated file so the parser hits EOF unexpectedly; Unicode issues producing a non-SyntaxError failure.","commonSituations":"Hand-writing JSON configs and giving a scalar where Caddy expects an object/array; disk-full writes truncating the config.","solutions":["Check the type at the reported field — the error names the Go type expected","Validate structure with jq and compare against the JSON config schema in the docs","If the input is not JSON at all, pass --adapter","Regenerate the file if it may be truncated (compare size against the producer's expectation)"],"exampleFix":"// before\n{ \"admin\": \"localhost:2019\" }\n\n// after\n{ \"admin\": { \"listen\": \"localhost:2019\" } }","handlingStrategy":"validation","validationCode":"// Type-check the top-level shape before passing the config along:\nvar probe map[string]json.RawMessage\nif err := json.Unmarshal(raw, &probe); err != nil { return fmt.Errorf(\"config JSON invalid: %w\", err) }\nif a, ok := probe[\"admin\"]; ok {\n    var admin caddy.AdminConfig\n    if err := json.Unmarshal(a, &admin); err != nil { return fmt.Errorf(\"admin field has wrong type: %w\", err) }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Schema-check generated configs (jq or a JSON Schema) in CI","Compare field types against the JSON config reference in the docs"],"tags":["cli","configuration","json","type-error"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}