{"record":{"id":"d07ec9c823602003","repo":"ipfs/kubo","slug":"creating-datastore-config-for-s-w","errorCode":null,"errorMessage":"creating datastore config for %s: %w","messagePattern":"creating datastore config for (.+?): %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/node/provider.go","lineNumber":499,"sourceCode":"\t\tclosers = append(closers, func() { ds.Close() })\n\t}\n\n\tcloser := func() {\n\t\tfor _, c := range closers {\n\t\t\tc()\n\t\t}\n\t}\n\treturn mounts, closer, nil\n}\n\n// openDatastoreAt opens a datastore using the given spec at the specified path.\n// It deep-copies the spec to avoid mutating the original.\nfunc openDatastoreAt(rootSpec map[string]any, path string) (datastore.Batching, error) {\n\tspec := copySpec(rootSpec)\n\tspec[\"path\"] = path\n\tdsc, err := fsrepo.AnyDatastoreConfig(spec)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"creating datastore config for %s: %w\", path, err)\n\t}\n\treturn dsc.Create(\"\")\n}\n\n// copySpec deep-copies a datastore spec map so modifications (e.g., changing\n// the path) don't affect the original.\nfunc copySpec(spec map[string]any) map[string]any {\n\tif spec == nil {\n\t\treturn nil\n\t}\n\tcp := make(map[string]any, len(spec))\n\tfor k, v := range spec {\n\t\tswitch val := v.(type) {\n\t\tcase map[string]any:\n\t\t\tcp[k] = copySpec(val)\n\t\tcase []any:\n\t\t\ts := make([]any, len(val))\n\t\t\tfor i, elem := range val {","sourceCodeStart":481,"sourceCodeEnd":517,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/node/provider.go#L481-L517","documentation":"openDatastoreAt takes the root datastore spec from the repo config, deep-copies it, rewrites its \"path\" to point at a keystore directory, and asks fsrepo.AnyDatastoreConfig to turn the spec into a datastore config. If the spec is malformed or names an unknown/unsupported datastore type, the error is wrapped as \"creating datastore config for %s: %w\" with the offending path. This means the datastore Spec in your config could not be interpreted, not that opening the datastore failed (that would come from dsc.Create).","triggerScenarios":"MountKeystoreDatastores (or the anonymous caller) invoking openDatastoreAt with a cfg.Datastore.Spec whose structure fsrepo.AnyDatastoreConfig rejects: unknown \"type\", missing required fields, wrong nesting, or non-map child specs.","commonSituations":"Hand-edited or migrated Datastore.Spec in ~/.ipfs/config that is no longer valid; spec written for a newer kubo than the installed binary; typo'd datastore type (e.g. \"flatfs\" misspelled); spec referencing a mount/disk schema the fsrepo parser does not know.","solutions":["Read the wrapped cause: it names the exact spec problem (unknown type, missing field, etc.) for the path shown in the message.","Compare your Datastore.Spec against a freshly initialized repo's spec (ipfs init in a temp IPFS_PATH, then ipfs config show) and correct the divergent keys.","Run `ipfs datastore verify` / upgrade to a kubo version that supports the datastore type named in your spec.","Regenerate the spec with `ipfs profile apply` or restore the default spec if it was hand-edited.","If you maintain this code, verify findRootDatastoreSpec returned the actual root spec map and that copySpec preserved required fields."],"exampleFix":"// before (spec with unparseable entry)\n{\n  \"type\": \"mount\",\n  \"mounts\": [\n    {\"mountpoint\": \"/keys\", \"type\": \"levelds\", \"path\": \"keys\"}\n  ]\n}\n// after (valid flatfs entry)\n{\n  \"type\": \"mount\",\n  \"mounts\": [\n    {\"mountpoint\": \"/keys\", \"type\": \"flatfs\", \"path\": \"keys\", \"shardFunc\": \"/repo/flatfs/shard/v1/next-to-last/2\"}\n  ]\n}","handlingStrategy":"validation","validationCode":"func validateSpec(spec map[string]any) error {\n    t, ok := spec[\"type\"].(string)\n    if !ok || t == \"\" {\n        return fmt.Errorf(\"datastore spec missing string 'type'\")\n    }\n    if t == \"mount\" {\n        mounts, ok := spec[\"mounts\"].([]any)\n        if !ok || len(mounts) == 0 {\n            return fmt.Errorf(\"mount spec has no mounts array\")\n        }\n        for i, m := range mounts {\n            if _, ok := m.(map[string]any); !ok {\n                return fmt.Errorf(\"mount[%d] is not an object\", i)\n            }\n        }\n    }\n    return nil\n}\n// call before MountKeystoreDatastores: validateSpec(cfg.Datastore.Spec.(map[string]any))","typeGuard":null,"tryCatchPattern":"dsCfg, err := fsrepo.AnyDatastoreConfig(spec)\nif err != nil {\n    if strings.Contains(err.Error(), \"unknown datastore type\") ||\n        errors.Is(err, datastore.ErrUnknownType) {\n        return nil, fmt.Errorf(\"config names an unsupported datastore type; upgrade kubo or fix Datastore.Spec: %w\", err)\n    }\n    return nil, fmt.Errorf(\"creating datastore config for %s: %w\", path, err)\n}","preventionTips":["Never hand-edit Datastore.Spec; use `ipfs config` or profile applies","Keep kubo and its datastore-capable deps upgraded together","Diff your spec against a fresh `ipfs init` spec after major upgrades","Deep-copy specs before mutation so a failed open leaves the original intact"],"tags":["go","datastore","config","spec"],"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"}