AlistGo/alist · error

failed to re-encrypt node passphrase: %w

Error message

failed to re-encrypt node passphrase: %w

What it means

DirectMove failed to re-encrypt the node's passphrase for the destination parent (reencryptNodePassphrase, util.go:815-847): it derives source-parent and destination-parent keyrings and re-wraps the link's NodePassphrase key packet. Failures are parent-link fetch errors, keyring derivation failures (shared folder / signature issues), or PGP errors in reencryptKeyPacket — undecryptable armored passphrase, wrong session-key packet, or encryption with the destination keyring failing.

Source

Thrown at drivers/proton_drive/util.go:778

	encryptedName, err := d.encryptFileName(ctx, srcObj.GetName(), dstParentLinkID)
	if err != nil {
		return nil, fmt.Errorf("failed to encrypt filename: %w", err)
	}

	newHash, err := d.generateNameHash(ctx, srcObj.GetName(), dstParentLinkID)
	if err != nil {
		return nil, fmt.Errorf("failed to generate new hash: %w", err)
	}

	originalHash, err := d.getOriginalNameHash(srcLink)
	if err != nil {
		return nil, fmt.Errorf("failed to get original hash: %w", err)
	}

	// Re-encrypt node passphrase for new parent context
	reencryptedPassphrase, err := d.reencryptNodePassphrase(ctx, srcLink, dstParentLinkID)
	if err != nil {
		return nil, fmt.Errorf("failed to re-encrypt node passphrase: %w", err)
	}

	moveReq := MoveRequest{
		ParentLinkID:       dstParentLinkID,
		NodePassphrase:     reencryptedPassphrase,
		Name:               encryptedName,
		NameSignatureEmail: d.MainShare.Creator,
		Hash:               newHash,
		OriginalHash:       originalHash,
		ContentHash:        nil,

		// *** Causes rejection ***
		/* NodePassphraseSignature: srcLink.NodePassphraseSignature, */
	}

	//fmt.Printf("DEBUG MoveRequest validation:\n")
	//fmt.Printf("  Name length: %d\n", len(moveReq.Name))
	//fmt.Printf("  Hash: %s\n", moveReq.Hash)

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Check the wrapped error to localize: 'failed to get source/destination parent keyring' vs 'failed to re-encrypt key packet'
  2. For keyring errors, re-initialize the driver (fresh address/share keys) and retry
  3. Verify read+decrypt access on BOTH source parent and destination parent (list both folders)
  4. If NodePassphrase is empty/invalid, re-fetch the source link with full metadata
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight both parents must be listable (keyrings derivable)
if _, err := d.List(ctx, srcParent); err != nil { return err }
if _, err := d.List(ctx, dstDir); err != nil { return err }
if srcLink.NodePassphrase == "" { return fmt.Errorf("source link lacks passphrase") }

Try / catch

if err := d.DirectMove(ctx, src, dst); err != nil {
    if strings.Contains(err.Error(), "failed to re-encrypt node passphrase") {
        // keyring access problem on source or destination parent:
        // re-init driver (fresh address/share keys), verify share membership, retry once
    }
}

Prevention

When it happens

Trigger: Moving between shares where either parent keyring cannot be derived; srcLink.NodePassphrase empty or not a valid armored PGP split message; account keys revoked after password reset so DecryptSessionKey fails; destination in a share not re-shared to this account's keys.

Common situations: Cross-share moves (personal -> shared or shared -> shared); mounts surviving a Proton password reset with stale keyrings; moving items whose passphrase was rotated by another client while cached.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/3efae01812d62bff. Report an issue: GitHub.