ipfs/kubo · error

unable to unmarshall format=%s: %w

Error message

unable to unmarshall format=%s: %w

What it means

The input was not a PEM block, but crypto.UnmarshalPrivateKey (libp2p protobuf-cleartext format) failed to decode the bytes as a valid libp2p private key. The wrapped error carries the underlying protobuf/unmarshal reason.

Source

Thrown at core/commands/keystore.go:521

			// In case ed25519.PrivateKey is returned we need the pointer for
			// conversion to libp2p (see export command for more details).
			if ed25519KeyPointer, ok := stdKey.(ed25519.PrivateKey); ok {
				stdKey = &ed25519KeyPointer
			}

			sk, _, err = crypto.KeyPairFromStdKey(stdKey)
			if err != nil {
				return fmt.Errorf("converting std Go key to libp2p key: %w", err)
			}
		case keyFormatLibp2pCleartextOption:
			sk, err = crypto.UnmarshalPrivateKey(data)
			if err != nil {
				// check if data is PEM, if so, provide user with hint
				pemBlock, _ := pem.Decode(data)
				if pemBlock != nil {
					return fmt.Errorf("unexpected PEM block for format=%s: try again with format=%s", keyFormatLibp2pCleartextOption, keyFormatPemCleartextOption)
				}
				return fmt.Errorf("unable to unmarshall format=%s: %w", keyFormatLibp2pCleartextOption, err)
			}

		default:
			return fmt.Errorf("unrecognized import format: %s", importFormat)
		}

		// We only allow importing keys of the same type we generate (see list in
		// https://github.com/ipfs/interface-go-ipfs-core/blob/1c3d8fc/options/key.go#L58-L60),
		// unless explicitly stated by the user.
		allowAnyKeyType, _ := req.Options[keyAllowAnyTypeOptionName].(bool)
		if !allowAnyKeyType {
			switch t := sk.(type) {
			case *crypto.RsaPrivateKey, *crypto.Ed25519PrivateKey, *crypto.Secp256k1PrivateKey:
			default:
				return fmt.Errorf("key type %T is not allowed to be imported, only RSA, Ed25519, or Secp256k1;"+
					" use flag --%s if you are sure of what you're doing",
					t, keyAllowAnyTypeOptionName)
			}

View on GitHub (pinned to 329838acdf)

Solutions

  1. Confirm the file's origin and format: `file keyfile` and compare with how it was exported (`ipfs key export --format=...`)
  2. Re-export the key from the source node and retry the import
  3. If it is a PEM key, use `-f pem-pkcs8-cleartext` (note error 343 covers the detectable PEM case)
  4. Check file size/integrity; re-copy if the transfer may have truncated it

Example fix

// before: format mismatch between export and import
$ ipfs key export mykey -f pem-pkcs8-cleartext > k.pem && ipfs key import mykey k.pem
Error: unable to unmarshall format=libp2p-protobuf-cleartext: ...
// after: match formats
$ ipfs key import mykey -f pem-pkcs8-cleartext k.pem
Defensive patterns

Strategy: validation

Validate before calling

info, _ := os.Stat(keyFile)
if info.Size() == 0 || info.Size() < 16 {
    return fmt.Errorf("key file %s looks truncated or empty", keyFile)
}
// also verify it is not PEM (that needs -f pem-pkcs8-cleartext)

Try / catch

if err := importKey(); err != nil {
    if strings.Contains(err.Error(), "unable to unmarshall") {
        // wrong format or corrupt file: re-export from source node
    }
}

Prevention

When it happens

Trigger: `ipfs key import name keyfile` (default format) where keyfile is garbage, a corrupted export from `ipfs key export`, a raw openssl/PEM-ish file that pem.Decode also rejects, or a truncated protobuf key.

Common situations: Importing a file exported with a different `--format` than used at import time, binary corruption during transfer, or accidentally importing a public key or certificate.

Related errors


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