ipfs/kubo · error

invalid type '%s', must be one of {direct, indirect, recursi

Error message

invalid type '%s', must be one of {direct, indirect, recursive, all}

What it means

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.

Source

Thrown at core/coreapi/pin.go:66

}

func (api *PinAPI) Ls(ctx context.Context, pins chan<- coreiface.Pin, opts ...caopts.PinLsOption) error {
	ctx, span := tracing.Span(ctx, "CoreAPI.PinAPI", "Ls")
	defer span.End()

	settings, err := caopts.PinLsOptions(opts...)
	if err != nil {
		close(pins)
		return err
	}

	span.SetAttributes(attribute.String("type", settings.Type))

	switch settings.Type {
	case "all", "direct", "indirect", "recursive":
	default:
		close(pins)
		return fmt.Errorf("invalid type '%s', must be one of {direct, indirect, recursive, all}", settings.Type)
	}

	return api.pinLsAll(ctx, settings.Type, settings.Detailed, settings.Name, pins)
}

func (api *PinAPI) IsPinned(ctx context.Context, p path.Path, opts ...caopts.PinIsPinnedOption) (string, bool, error) {
	ctx, span := tracing.Span(ctx, "CoreAPI.PinAPI", "IsPinned", trace.WithAttributes(attribute.String("path", p.String())))
	defer span.End()

	resolved, _, err := api.core().ResolvePath(ctx, p)
	if err != nil {
		return "", false, fmt.Errorf("error resolving path: %s", err)
	}

	settings, err := caopts.PinIsPinnedOptions(opts...)
	if err != nil {
		return "", false, err
	}

View on GitHub (pinned to 329838acdf)

Solutions

  1. Use exactly one of: direct, indirect, recursive, all (lowercase)
  2. Use 'all' when you want every pin
  3. Validate the type string before constructing options

Example fix

// before
api.Pin().Ls(ctx, ch, caopts.PinLsOptions{Type: "Recursive"})
// after
api.Pin().Ls(ctx, ch, caopts.PinLsOptions{Type: "recursive"})
Defensive patterns

Strategy: validation

Validate before calling

var validPinTypes = map[string]struct{}{"direct":{}, "indirect":{}, "recursive":{}, "all":{}}
func validPinType(t string) bool { _, ok := validPinTypes[t]; return ok }

Type guard

func validPinType(t string) bool {
	switch t {
	case "all", "direct", "indirect", "recursive":
		return true
	}
	return false
}

Try / catch

if !validPinType(settings.Type) {
    return fmt.Errorf("invalid pin type %q", settings.Type)
}
_ = api.Pin().Ls(ctx, ch, caopts.PinLsOptions{Type: settings.Type})

Prevention

When it happens

Trigger: 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.

Common situations: Scripts building pin/ls queries with hand-typed type strings; locale/format mistakes like 'Recursive' (case-sensitive check).

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/09041d75c629b77a. Report an issue: GitHub.