{"record":{"id":"7ce49041f977b21d","repo":"ipfs/kubo","slug":"mounts-field-is-missing-or-not-an-array","errorCode":null,"errorMessage":"'mounts' field is missing or not an array","messagePattern":"'mounts' field is missing or not an array","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"repo/fsrepo/datastores.go","lineNumber":104,"sourceCode":"\t}\n\treturn fun(params)\n}\n\ntype mountDatastoreConfig struct {\n\tmounts []premount\n}\n\ntype premount struct {\n\tds     DatastoreConfig\n\tprefix ds.Key\n}\n\n// MountDatastoreConfig returns a mount DatastoreConfig from a spec.\nfunc MountDatastoreConfig(params map[string]any) (DatastoreConfig, error) {\n\tvar res mountDatastoreConfig\n\tmounts, ok := params[\"mounts\"].([]any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"'mounts' field is missing or not an array\")\n\t}\n\tfor _, iface := range mounts {\n\t\tcfg, ok := iface.(map[string]any)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"expected map for mountpoint\")\n\t\t}\n\n\t\tchild, err := AnyDatastoreConfig(cfg)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tprefix, found := cfg[\"mountpoint\"]\n\t\tif !found {\n\t\t\treturn nil, fmt.Errorf(\"no 'mountpoint' on mount\")\n\t\t}\n\n\t\tres.mounts = append(res.mounts, premount{","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/repo/fsrepo/datastores.go#L86-L122","documentation":"MountDatastoreConfig parses a mount (multi-mount) datastore spec and requires params[\"mounts\"] to be an array of mount specs. The error is thrown when the \"mounts\" key is missing or its value is not []any, since there is nothing to iterate to build the mount table.","triggerScenarios":"Calling MountDatastoreConfig(params) with params lacking \"mounts\", or where params[\"mounts\"] is a string, map, or was unmarshalled into a typed struct instead of []any.","commonSituations":"Spec in the repo config with type \"mounts\" but the mounts array renamed, removed, or given as an object; manual JSON edit; a templating tool that emits an empty object instead of an array.","solutions":["Add a \"mounts\" key holding an array of mount specs, each a map with its own \"mountpoint\" and \"child\"","Fix JSON parsing so the value arrives as []any (json.Unmarshal into map[string]any gives arrays as []any)","If no mounts are needed, use a non-mount datastore type instead of an empty/invalid mounts spec"],"exampleFix":"// before\nspec := map[string]any{\"type\": \"mounts\"}\n// after\nspec := map[string]any{\"type\": \"mounts\", \"mounts\": []any{\n  map[string]any{\"mountpoint\": \"/blocks\", \"child\": map[string]any{\"type\": \"flatfs\", \"path\": \"blocks\", \"sync\": true}},\n  map[string]any{\"mountpoint\": \"/\", \"child\": map[string]any{\"type\": \"levelds\", \"path\": \"datastore\"}},\n}}","handlingStrategy":"validation","validationCode":"m, ok := params[\"mounts\"].([]any)\nif !ok || len(m) == 0 { /* add a valid mounts array before calling */ }","typeGuard":"func mountsArray(params map[string]any) ([]any, bool) {\n\tm, ok := params[\"mounts\"].([]any)\n\treturn m, ok && len(m) > 0\n}","tryCatchPattern":"ds, err := fsrepo.MountDatastoreConfig(spec)\nif err != nil {\n\tif strings.Contains(err.Error(), \"'mounts' field\") {\n\t\treturn fmt.Errorf(\"mount spec requires a mounts array: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Always emit \"mounts\" as a JSON array of objects, never an object or string","Never leave an empty or placeholder mounts value in generated specs","Use a non-mount datastore type when only one datastore is needed"],"tags":["datastore","config","mount","validation","go"],"backgroundTag":"datastore-spec-invalid","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}