{"record":{"id":"27965e1c2485ba10","repo":"ipfs/kubo","slug":"child-field-is-missing-or-not-a-map","errorCode":null,"errorMessage":"'child' field is missing or not a map","messagePattern":"'child' field is missing or not a map","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"repo/fsrepo/datastores.go","lineNumber":189,"sourceCode":"\nfunc (c *memDatastoreConfig) DiskSpec() DiskSpec {\n\treturn nil\n}\n\nfunc (c *memDatastoreConfig) Create(string) (repo.Datastore, error) {\n\treturn dssync.MutexWrap(ds.NewMapDatastore()), nil\n}\n\ntype logDatastoreConfig struct {\n\tchild DatastoreConfig\n\tname  string\n}\n\n// LogDatastoreConfig returns a log DatastoreConfig from a spec.\nfunc LogDatastoreConfig(params map[string]any) (DatastoreConfig, error) {\n\tchildField, ok := params[\"child\"].(map[string]any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"'child' field is missing or not a map\")\n\t}\n\tchild, err := AnyDatastoreConfig(childField)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tname, ok := params[\"name\"].(string)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"'name' field was missing or not a string\")\n\t}\n\treturn &logDatastoreConfig{child, name}, nil\n}\n\nfunc (c *logDatastoreConfig) Create(path string) (repo.Datastore, error) {\n\tchild, err := c.child.Create(path)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn ds.NewLogDatastore(child, c.name), nil","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/repo/fsrepo/datastores.go#L171-L207","documentation":"LogDatastoreConfig wraps another datastore for event logging, and that wrapped datastore must be given as a nested spec under params[\"child\"]. The error is thrown when \"child\" is missing or not a map[string]any, since a child DatastoreConfig cannot be constructed without it.","triggerScenarios":"Calling LogDatastoreConfig(params) with no \"child\" key, or where params[\"child\"] is a string, bool, or already-constructed struct instead of a nested spec map.","commonSituations":"Spec of type \"log\" written without the nested child datastore; child spec supplied as a JSON string instead of an object; someone inlined the child fields at the top level instead of nesting them.","solutions":["Add a \"child\" key containing a full nested datastore spec map (with its own \"type\" and options)","If the child was passed as a JSON string, unmarshal it into map[string]any first","Move any top-level child datastore fields into the nested child object"],"exampleFix":"// before\nspec := map[string]any{\"type\": \"log\", \"name\": \"dslog\"}\n// after\nspec := map[string]any{\"type\": \"log\", \"name\": \"dslog\", \"child\": map[string]any{\"type\": \"flatfs\", \"path\": \"blocks\"}}","handlingStrategy":"validation","validationCode":"c, ok := params[\"child\"].(map[string]any)\nif !ok { /* add nested child spec before calling */ }","typeGuard":"func childSpec(params map[string]any) (map[string]any, bool) {\n\tc, ok := params[\"child\"].(map[string]any)\n\treturn c, ok\n}","tryCatchPattern":"ds, err := fsrepo.LogDatastoreConfig(spec)\nif err != nil {\n\tif strings.Contains(err.Error(), \"'child' field\") {\n\t\treturn fmt.Errorf(\"log spec requires nested child: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Always nest the wrapped datastore spec under \"child\" as a map","Never pass the child as a JSON string; unmarshal to map[string]any first","Remember child specs need their own \"type\" key"],"tags":["datastore","config","log","nested-spec","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"}