ipfs/kubo · error

pin: %s

Error message

pin: %s

What it means

PinAPI.Add first resolves the given path to a node; any resolution failure (bad path, unsupported namespace, missing block) is wrapped with a 'pin: ' prefix. The error is a wrapper — the underlying cause (from ResolveNode) is embedded after the prefix.

Source

Thrown at core/coreapi/pin.go:30

	pin "github.com/ipfs/boxo/pinning/pinner"
	"github.com/ipfs/go-cid"
	coreiface "github.com/ipfs/kubo/core/coreiface"
	caopts "github.com/ipfs/kubo/core/coreiface/options"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/trace"

	"github.com/ipfs/kubo/tracing"
)

type PinAPI CoreAPI

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

	dagNode, err := api.core().ResolveNode(ctx, p)
	if err != nil {
		return fmt.Errorf("pin: %s", err)
	}

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

	span.SetAttributes(attribute.Bool("recursive", settings.Recursive))

	defer api.blockstore.PinLock(ctx).Unlock(ctx)

	err = api.pinning.Pin(ctx, dagNode, settings.Recursive, settings.Name)
	if err != nil {
		return fmt.Errorf("pin: %s", err)
	}

	return api.pinning.Flush(ctx)
}

View on GitHub (pinned to 329838acdf)

Solutions

  1. Read the wrapped cause after 'pin: ' to identify the real failure
  2. Verify the CID exists locally: 'ipfs block stat' or 'ipfs cat'
  3. Resolve IPNS/namespace issues before pinning (pin the /ipfs/ path)
  4. Ensure the daemon has connectivity to fetch the content before pinning

Example fix

// before
err := api.Pin().Add(ctx, path.New("/ipns/example.com")) // pin: unsupported path namespace
// after
nd, err := api.ResolveNode(ctx, path.New("/ipns/example.com"))
if err == nil {
    err = api.Pin().Add(ctx, path.FromCid(nd.Cid()))
}
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure path is /ipfs/-namespaced and the CID is present locally
_, err := api.Block().Stat(ctx, p)
if err != nil {
    // fetch/resolve before pinning
}

Type guard

func isIPFSPath(p path.Path) bool { return p.Namespace() == path.IPFSNamespace }

Try / catch

err := api.Pin().Add(ctx, p, opts...)
if err != nil {
    var cause error
    if strings.HasPrefix(err.Error(), "pin: ") {
        // unwrap and inspect the resolution failure after "pin: "
    }
    return fmt.Errorf("pin add failed: %w", err)
}

Prevention

When it happens

Trigger: Calling Pin().Add with a path that cannot be resolved: nonexistent CID, /ipns/ path, malformed path, or a path whose blocks are not present locally and cannot be fetched.

Common situations: Pinning a CID that exists on the network but the node is offline; pinning an IPNS name without the pin API supporting that namespace; typo'd CID.

Related errors


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