eyaltoledano/claude-task-master · error · AuthenticationError

DECRYPTION_FAILED

DECRYPTION_FAILED

Error message

`Token decryption failed: ${error instanceof Error ? error.message : 'Unknown error'}`

What it means

decryptTokens in cli-crypto wraps any failure while AES-decrypting the locally stored token blob into an AuthenticationError with code DECRYPTION_FAILED. It fires when decipher.update/final or the subsequent JSON.parse throws — i.e., the ciphertext, key, or stored format is invalid. The original error is preserved as the cause.

Source

Thrown at packages/tm-core/src/modules/auth/utils/cli-crypto.ts:101

				key: privateKeyPem,
				padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
				oaepHash: 'sha256'
			},
			encryptedKey
		);

		// Decrypt tokens using AES-256-GCM
		const decipher = crypto.createDecipheriv('aes-256-gcm', aesKey, iv);
		decipher.setAuthTag(authTag);

		const decrypted = Buffer.concat([
			decipher.update(encryptedData),
			decipher.final()
		]);

		return JSON.parse(decrypted.toString('utf8')) as DecryptedTokens;
	} catch (error) {
		throw new AuthenticationError(
			`Token decryption failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
			'DECRYPTION_FAILED',
			error
		);
	}
}

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Delete the stored credential/token file and log in again (tm auth login) to regenerate and re-encrypt tokens
  2. Restore the original encryption key/credentials or copy the tokens file from the original machine where it was encrypted
  3. Verify the tokens file is not truncated or manually modified; re-download from backup taken with the same key
  4. If this started after a version upgrade, re-authenticate so tokens are stored in the new format

Example fix

// before
const tokens = crypto.decryptTokens(encrypted); // throws DECRYPTION_FAILED
// after
let tokens;
try {
  tokens = crypto.decryptTokens(encrypted);
} catch (e) {
  if (e instanceof AuthenticationError && e.code === 'DECRYPTION_FAILED') {
    await reAuthenticate(); // clears stale tokens and logs in again
    return;
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

import { existsSync } from 'fs';
const tokensPath = crypto.tokensFilePath;
if (!existsSync(tokensPath)) await reAuthenticate();
else if (Buffer.byteLength(readFileSync(tokensPath)) === 0) await reAuthenticate(); // empty/corrupt

Type guard

function isDecryptionFailed(e: unknown): e is AuthenticationError {
  return e instanceof AuthenticationError && e.code === 'DECRYPTION_FAILED';
}

Try / catch

try {
  tokens = decryptTokens(encrypted);
} catch (e) {
  if (isDecryptionFailed(e)) {
    await clearStoredCredentials();
    await reAuthenticate(); // tokens unreadable: log in again
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling decryptTokens when the encrypted tokens file was written with a different key (machine/user change), the file is corrupted or truncated, or the decrypted plaintext is not valid JSON (JSON.parse throws).

Common situations: Restoring ~/.task-master config from a backup onto another machine (different crypto key); manually editing or partially copying the token file; library upgrade changing the encryption format; disk corruption.

Related errors


AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29). Data as JSON: /api/errors/1fb3c244cb1f6960. Report an issue: GitHub.