pnpm/pnpm · error · TokenHelperUnsupportedCharacterError
TOKEN_HELPER_UNSUPPORTED_CHARACTER
TOKEN_HELPER_UNSUPPORTED_CHARACTER
Error message
Unexpected character ${JSON.stringify(char)} What it means
The `tokenHelper` rc key is parsed with a deliberately minimal grammar: the value is trimmed, split on whitespace into command plus arguments, and nothing else. The characters `$`, `%`, backtick, `"`, and `'` are reserved for future features (quoting and env interpolation), so any occurrence throws TOKEN_HELPER_UNSUPPORTED_CHARACTER. The error exposes the offending char and a hint specific to quotes vs env vars.
Source
Thrown at pnpm11/config/reader/src/parseCreds.ts:142
}
}
/** Characters reserved for more advanced features in the future. */
const RESERVED_CHARACTERS = new Set(['$', '%', '`', '"', "'"])
/**
* Parse a value of `tokenHelper` from an rc file into an array of
* token helper command and its arguments.
*/
function parseTokenHelper (source: string): TokenHelper {
source = source.trim()
for (const char of source) {
// We'll only support a simple syntax for now.
// In the future, we may add quotations and environment variable interpolations.
if (RESERVED_CHARACTERS.has(char)) {
throw new TokenHelperUnsupportedCharacterError(char)
}
}
const command = source.split(/\s+/).filter(Boolean)
return command as [string, ...string[]]
}
export class TokenHelperUnsupportedCharacterError extends PnpmError {
readonly char: string
constructor (char: string) {
let hint = 'Try wrapping the current command in a script whose name does not contain unsupported characters'
if (char === '"' || char === "'") {
hint = `pnpm does not support quotations in tokenHelper. ${hint}`
} else if (char === '$' || char === '%') {
hint = `pnpm does not support environment variables. ${hint}`
}
super('TOKEN_HELPER_UNSUPPORTED_CHARACTER', `Unexpected character ${JSON.stringify(char)}`, { hint })View on GitHub (pinned to 5b11d3a15b)
Solutions
- Drop the quotes — tokenHelper only accepts plain whitespace-separated tokens
- Move quoting, env access, or shell logic into a small wrapper script and set tokenHelper to its path (plus simple args)
- Ensure the helper path itself contains no spaces or reserved characters
Example fix
# before (.npmrc) tokenHelper=/bin/sh -c "cat $HOME/.npm-token" # after — /usr/local/bin/fetch-npm-token is a script doing `cat "$HOME/.npm-token"` tokenHelper=/usr/local/bin/fetch-npm-token
Defensive patterns
Strategy: validation
Validate before calling
const TOKEN_HELPER_RESERVED = new Set(['$', '%', '`', '"', "'"])
function isParsableTokenHelper (value: string): boolean {
const s = value.trim()
return s.length > 0 && Array.from(s).every(ch => !TOKEN_HELPER_RESERVED.has(ch))
} Try / catch
catch (err) {
if (err instanceof PnpmError && err.code === 'TOKEN_HELPER_UNSUPPORTED_CHARACTER') {
// err.char is the offending character; err.hint suggests a wrapper script
} else throw err
} Prevention
- Keep tokenHelper a bare executable path plus simple args
- Put quoting and env-var logic in a wrapper script
- Document the reserved characters ($ % ` " ') in team docs
When it happens
Trigger: tokenHelper=/bin/sh -c "cat ~/.npm-token" (quotes), tokenHelper=./get-token $NPM_TOKEN (POSIX env var), tokenHelper=helper.cmd %TOKEN% (Windows env var), or any backtick command substitution.
Common situations: Porting a shell one-liner from another tool's config; trying to pass an argument containing spaces via quotes; CI setups that want the token through an environment variable.
Related errors
- TOKEN_HELPER_IN_PROJECT_CONFIG
- AUTH_MISSING_SEPARATOR
- AUTH_INVALID_BASE64
- LOGIN_NON_INTERACTIVE
- LOGIN_CANCELED
AI-assisted analysis of pnpm/pnpm@5b11d3a15b (2026-08-16).
Data as JSON: /api/errors/ac6981d63a88f1d0.
Report an issue: GitHub.