ipfs/kubo · error
creating datastore config for
Error message
creating datastore config for %s: %w
What it means
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).
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.
Example fix
// before (spec with unparseable entry)
{
"type": "mount",
"mounts": [
{"mountpoint": "/keys", "type": "levelds", "path": "keys"}
]
}
// after (valid flatfs entry)
{
"type": "mount",
"mounts": [
{"mountpoint": "/keys", "type": "flatfs", "path": "keys", "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2"}
]
} Defensive patterns
Strategy: validation
Validate before calling
func validateSpec(spec map[string]any) error {
t, ok := spec["type"].(string)
if !ok || t == "" {
return fmt.Errorf("datastore spec missing string 'type'")
}
if t == "mount" {
mounts, ok := spec["mounts"].([]any)
if !ok || len(mounts) == 0 {
return fmt.Errorf("mount spec has no mounts array")
}
for i, m := range mounts {
if _, ok := m.(map[string]any); !ok {
return fmt.Errorf("mount[%d] is not an object", i)
}
}
}
return nil
}
// call before MountKeystoreDatastores: validateSpec(cfg.Datastore.Spec.(map[string]any)) Try / catch
dsCfg, err := fsrepo.AnyDatastoreConfig(spec)
if err != nil {
if strings.Contains(err.Error(), "unknown datastore type") ||
errors.Is(err, datastore.ErrUnknownType) {
return nil, fmt.Errorf("config names an unsupported datastore type; upgrade kubo or fix Datastore.Spec: %w", err)
}
return nil, fmt.Errorf("creating datastore config for %s: %w", path, err)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- 'child' field is missing or not a map
- expected map for mountpoint
- 'mounts' field is missing or not an array
- 'name' field was missing or not a string
- no 'mountpoint' on mount
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/d07ec9c823602003.
Report an issue: GitHub.
Appendix: source
Thrown at core/node/provider.go:499
closers = append(closers, func() { ds.Close() })
}
closer := func() {
for _, c := range closers {
c()
}
}
return mounts, closer, nil
}
// openDatastoreAt opens a datastore using the given spec at the specified path.
// It deep-copies the spec to avoid mutating the original.
func openDatastoreAt(rootSpec map[string]any, path string) (datastore.Batching, error) {
spec := copySpec(rootSpec)
spec["path"] = path
dsc, err := fsrepo.AnyDatastoreConfig(spec)
if err != nil {
return nil, fmt.Errorf("creating datastore config for %s: %w", path, err)
}
return dsc.Create("")
}
// copySpec deep-copies a datastore spec map so modifications (e.g., changing
// the path) don't affect the original.
func copySpec(spec map[string]any) map[string]any {
if spec == nil {
return nil
}
cp := make(map[string]any, len(spec))
for k, v := range spec {
switch val := v.(type) {
case map[string]any:
cp[k] = copySpec(val)
case []any:
s := make([]any, len(val))
for i, elem := range val {View on GitHub (pinned to 329838acdf)