{"record":{"id":"09041d75c629b77a","repo":"ipfs/kubo","slug":"invalid-type-s-must-be-one-of-direct-indirec-09041d","errorCode":null,"errorMessage":"invalid type '%s', must be one of {direct, indirect, recursive, all}","messagePattern":"invalid type '(.+?)', must be one of (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/coreapi/pin.go","lineNumber":66,"sourceCode":"}\n\nfunc (api *PinAPI) Ls(ctx context.Context, pins chan<- coreiface.Pin, opts ...caopts.PinLsOption) error {\n\tctx, span := tracing.Span(ctx, \"CoreAPI.PinAPI\", \"Ls\")\n\tdefer span.End()\n\n\tsettings, err := caopts.PinLsOptions(opts...)\n\tif err != nil {\n\t\tclose(pins)\n\t\treturn err\n\t}\n\n\tspan.SetAttributes(attribute.String(\"type\", settings.Type))\n\n\tswitch settings.Type {\n\tcase \"all\", \"direct\", \"indirect\", \"recursive\":\n\tdefault:\n\t\tclose(pins)\n\t\treturn fmt.Errorf(\"invalid type '%s', must be one of {direct, indirect, recursive, all}\", settings.Type)\n\t}\n\n\treturn api.pinLsAll(ctx, settings.Type, settings.Detailed, settings.Name, pins)\n}\n\nfunc (api *PinAPI) IsPinned(ctx context.Context, p path.Path, opts ...caopts.PinIsPinnedOption) (string, bool, error) {\n\tctx, span := tracing.Span(ctx, \"CoreAPI.PinAPI\", \"IsPinned\", trace.WithAttributes(attribute.String(\"path\", p.String())))\n\tdefer span.End()\n\n\tresolved, _, err := api.core().ResolvePath(ctx, p)\n\tif err != nil {\n\t\treturn \"\", false, fmt.Errorf(\"error resolving path: %s\", err)\n\t}\n\n\tsettings, err := caopts.PinIsPinnedOptions(opts...)\n\tif err != nil {\n\t\treturn \"\", false, err\n\t}","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/coreapi/pin.go#L48-L84","documentation":"PinAPI.Ls validates the settings.Type filter against the four allowed values (direct, indirect, recursive, all) before listing; any other string is rejected and the output channel is closed. The message echoes the invalid type and lists valid values.","triggerScenarios":"Passing PinLsOptions with Type set to e.g. 'recursive+' , 'all pins', an empty string not normalized, or CLI --type with a typo via the RPC pin/ls endpoint.","commonSituations":"Scripts building pin/ls queries with hand-typed type strings; locale/format mistakes like 'Recursive' (case-sensitive check).","solutions":["Use exactly one of: direct, indirect, recursive, all (lowercase)","Use 'all' when you want every pin","Validate the type string before constructing options"],"exampleFix":"// before\napi.Pin().Ls(ctx, ch, caopts.PinLsOptions{Type: \"Recursive\"})\n// after\napi.Pin().Ls(ctx, ch, caopts.PinLsOptions{Type: \"recursive\"})","handlingStrategy":"validation","validationCode":"var validPinTypes = map[string]struct{}{\"direct\":{}, \"indirect\":{}, \"recursive\":{}, \"all\":{}}\nfunc validPinType(t string) bool { _, ok := validPinTypes[t]; return ok }","typeGuard":"func validPinType(t string) bool {\n\tswitch t {\n\tcase \"all\", \"direct\", \"indirect\", \"recursive\":\n\t\treturn true\n\t}\n\treturn false\n}","tryCatchPattern":"if !validPinType(settings.Type) {\n    return fmt.Errorf(\"invalid pin type %q\", settings.Type)\n}\n_ = api.Pin().Ls(ctx, ch, caopts.PinLsOptions{Type: settings.Type})","preventionTips":["Centralize pin type constants in your client code","Validate user-supplied --type values against the enum before the call","Remember the check is case-sensitive lowercase"],"tags":["pin","validation","bad-request"],"backgroundTag":"invalid-enum-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"}