{"record":{"id":"604dc349b416a415","repo":"ipfs/kubo","slug":"unable-to-parse-byte-size-expected-a-size-string","errorCode":null,"errorMessage":"unable to parse byte size, expected a size string (e.g., \"5GiB\") or a number, but got %T","messagePattern":"unable to parse byte size, expected a size string \\(e\\.g\\., \"5GiB\"\\) or a number, but got %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/types.go","lineNumber":504,"sourceCode":"\t\t*p = OptionalBytes{}\n\tdefault:\n\t\tvar value any\n\t\terr := json.Unmarshal(input, &value)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tswitch v := value.(type) {\n\t\tcase float64:\n\t\t\tstr := fmt.Sprintf(\"%.0f\", v)\n\t\t\tp.value = &str\n\t\tcase string:\n\t\t\t_, err := humanize.ParseBytes(v)\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tp.value = &v\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"unable to parse byte size, expected a size string (e.g., \\\"5GiB\\\") or a number, but got %T\", v)\n\t\t}\n\t}\n\treturn nil\n}\n\nvar (\n\t_ json.Unmarshaler = (*OptionalBytes)(nil)\n\t_ json.Marshaler   = (*OptionalBytes)(nil)\n)\n\ntype swarmLimits doNotUse\n\nvar _ json.Unmarshaler = swarmLimits(false)\n\nfunc (swarmLimits) UnmarshalJSON(b []byte) error {\n\td := json.NewDecoder(bytes.NewReader(b))\n\tfor {\n\t\tswitch tok, err := d.Token(); err {","sourceCodeStart":486,"sourceCodeEnd":522,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/config/types.go#L486-L522","documentation":"The byte-size config type accepts a size string parsed by dustin/go-humanize (e.g. \"5GiB\", \"10MB\") or a plain JSON number of bytes. Any other JSON type hits the default branch and is rejected with this error.","triggerScenarios":"Unmarshaling a Datastore/StorageMax-style size field with an object, boolean, or array value, e.g. {\"StorageMax\": {\"value\": \"10GB\"}}.","commonSituations":"Converting config from another tool that wraps sizes in objects; hand-editing config.json with a boolean placeholder; template rendering leaving a non-scalar value.","solutions":["Use a human-readable size string: {\"StorageMax\": \"10GB\"}.","Or use a plain byte count number: {\"StorageMax\": 10000000000}.","Verify the value with `ipfs config --json Datastore.StorageMax` after editing."],"exampleFix":"// before\n{\"Datastore\": {\"StorageMax\": {\"size\": \"10GB\"}}}\n// after\n{\"Datastore\": {\"StorageMax\": \"10GB\"}}","handlingStrategy":"validation","validationCode":"func validByteSize(v any) error {\n    switch t := v.(type) {\n    case string:\n        _, err := humanize.ParseBytes(t)\n        return err\n    case float64:\n        return nil // raw bytes\n    default:\n        return fmt.Errorf(\"byte size must be string like \\\"5GiB\\\" or number, got %T\", v)\n    }\n}","typeGuard":"func isByteSizeValue(v any) bool {\n    switch t := v.(type) {\n    case string:\n        _, err := humanize.ParseBytes(t)\n        return err == nil\n    case float64:\n        return true\n    }\n    return false\n}","tryCatchPattern":"if err := json.Unmarshal(data, &cfg); err != nil {\n    if strings.Contains(err.Error(), \"unable to parse byte size\") {\n        // fix to \"10GB\" string or byte count number\n    }\n}","preventionTips":["Store sizes as plain strings like \"10GB\" or byte numbers, never nested objects","Pre-validate with humanize.ParseBytes in config generators","Round-trip test config marshal/unmarshal in CI"],"tags":["config","json-parsing","byte-size"],"backgroundTag":"invalid-config-value","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"}