{"record":{"id":"f052bf5d46aff379","repo":"IceWhaleTech/CasaOS","slug":"create-config-failed","errorCode":null,"errorMessage":"create config failed","messagePattern":"create config failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/utils/httper/drive.go","lineNumber":126,"sourceCode":"\n\tlogger.Info(\"unmount then\", zap.Any(\"res\", res.Body()))\n\treturn nil\n}\n\nfunc CreateConfig(data map[string]string, name, t string) error {\n\tdata[\"config_is_local\"] = \"false\"\n\tdataStr, _ := json.Marshal(data)\n\tres, err := NewRestyClient().R().SetFormData(map[string]string{\n\t\t\"name\":       name,\n\t\t\"parameters\": string(dataStr),\n\t\t\"type\":       t,\n\t}).Post(\"/config/create\")\n\tlogger.Info(\"when create config then\", zap.Any(\"res\", res.Body()))\n\tif err != nil {\n\t\treturn err\n\t}\n\tif res.StatusCode() != 200 {\n\t\treturn fmt.Errorf(\"create config failed\")\n\t}\n\n\treturn nil\n}\n\nfunc GetConfigByName(name string) (map[string]string, error) {\n\n\tres, err := NewRestyClient().R().SetFormData(map[string]string{\n\t\t\"name\": name,\n\t}).Post(\"/config/get\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif res.StatusCode() != 200 {\n\t\treturn nil, fmt.Errorf(\"create config failed\")\n\t}\n\tvar result map[string]string\n\tjson.Unmarshal(res.Body(), &result)","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/IceWhaleTech/CasaOS/blob/0d3b2f444ec0193193cf03eef6d43c6e35b0183e/pkg/utils/httper/drive.go#L108-L144","documentation":"Returned by CreateConfig() in pkg/utils/httper/drive.go when POST /config/create responds non-200. This call creates an rclone remote config: it sends name, a JSON-serialized parameters map, and a backend type. rclone rejects creation when the name is duplicated, the type is unknown, or a required backend field is missing/invalid. Note the code logs the response before checking err, and also silently swallows the json.Marshal error via `_`.","triggerScenarios":"(1) A remote with the same name already exists (rclone config create on existing name fails unless update is forced), (2) t is not a valid rclone backend type string (e.g. 'onnedrive' instead of 'onedrive'), (3) parameters JSON is missing mandatory fields for the backend (client_id/secret, token), (4) the serialized parameters map is not valid rclone option syntax so rclone answers 400/500.","commonSituations":"Adding the same cloud drive twice from the CasaOS UI; typo'd or version-mismatched backend type after upgrading the rclone binary; OAuth token missing because the flow was never completed; parameter keys cased differently than rclone expects (rclone options are case-sensitive).","solutions":["Call GetAllConfigName() first and skip or delete-and-recreate if the name already exists.","Validate t against rclone's known backend list (rclone list backends / config providers endpoint) before creating.","Check res.Body() content: rclone returns a plain-text reason that names the failing option.","Handle the json.Marshal error instead of discarding it, so an unserializable map fails fast with a real message.","Move the logger.Info call after the err check so transport failures are not masked by a nil-dereference style panic."],"exampleFix":"// before\ndataStr, _ := json.Marshal(data)\nres, err := NewRestyClient().R().SetFormData(map[string]string{...}).Post(\"/config/create\")\nlogger.Info(\"when create config then\", zap.Any(\"res\", res.Body()))\nif err != nil {\n    return err\n}\nif res.StatusCode() != 200 {\n    return fmt.Errorf(\"create config failed\")\n}\n\n// after\ndataStr, err := json.Marshal(data)\nif err != nil {\n    return fmt.Errorf(\"marshal config parameters: %w\", err)\n}\nres, err := NewRestyClient().R().SetFormData(map[string]string{\n    \"name\":       name,\n    \"parameters\": string(dataStr),\n    \"type\":       t,\n}).Post(\"/config/create\")\nif err != nil {\n    return err\n}\nif res.StatusCode() != 200 {\n    return fmt.Errorf(\"create config failed: status=%d body=%s\", res.StatusCode(), res.Body())\n}","handlingStrategy":"validation","validationCode":"// before CreateConfig()\nnames, err := httper.GetAllConfigName()\nif err != nil {\n    return err\n}\nfor _, existing := range names.Remotes {\n    if existing == name {\n        return fmt.Errorf(\"remote %q already exists\", name)\n    }\n}\n// validate backend type against rclone's provider list before sending","typeGuard":null,"tryCatchPattern":"if err := httper.CreateConfig(params, name, backendType); err != nil {\n    if strings.Contains(err.Error(), \"create config failed\") {\n        // deterministic server-side rejection: fix inputs, do not retry\n        return fmt.Errorf(\"rclone rejected config %s (type %s): %w\", name, backendType, err)\n    }\n    return err // transport failure: safe to retry once\n}","preventionTips":["Always pre-check remote name uniqueness via listremotes.","Keep a whitelist of supported backend types and validate user input against it.","Handle the json.Marshal error; never discard it with _.","Log the response body on failure — rclone names the exact offending option."],"tags":["rclone","config","http-client","casaos"],"backgroundTag":null,"analyzedSha":"0d3b2f444ec0193193cf03eef6d43c6e35b0183e","analyzedAt":"2026-08-15T13:27:57.821Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}