| name | pat-expiration-silent |
| description | Personal Access Token expiration fails silently — 401 errors with no expiry message, pre-check pattern |
| lastReviewed | 2026-04-30T00:00:00.000Z |
PAT Expiration Silent Failure
Category: Windows / Node.js
Time Saved: 30 minutes debugging publish failures
Battle-tested: Yes — VS Code Marketplace publishing
The Problem
You run vsce publish or npm publish and it fails with a 401 error. Your VSCE_PAT or NPM_TOKEN environment variable is set. You just used it last week. What changed?
Why It Happens
Personal Access Tokens (PATs) have expiration dates. When they expire:
- The environment variable still exists
- Preflight checks that look for "is variable set?" pass
- The actual API call fails with 401 Unauthorized
- Error messages often don't say "token expired"
The Rule
Token existence ≠ token validity. The 401 at publish time is the first signal that your PAT expired.
Common Tokens and Their Lifespans
| Token | Max Lifespan | Typical Setting |
|---|
| Azure DevOps PAT | 1 year | 90 days default |
| GitHub PAT (classic) | No expiry option | 30-90 days recommended |
| GitHub PAT (fine-grained) | 1 year max | Organization policy |
| npm token | No expiry | Until revoked |
Detection Pattern
When you see a 401 during publish:
Step 1: Identify the Token
# Check which token is being used
echo $env:VSCE_PAT # For VS Code Marketplace
echo $env:NPM_TOKEN # For npm
echo $env:GH_TOKEN # For GitHub CLI
Step 2: Check Token Portal
| Service | Token Management URL |
|---|
| Azure DevOps | https://dev.azure.com/{org}/_usersSettings/tokens |
| GitHub | https://github.com/settings/tokens |
| npm | https://www.npmjs.com/settings/~/tokens |
Step 3: Regenerate and Update
# After creating new token, update env var
$env:VSCE_PAT = "new-token-value"
# Or set permanently
[Environment]::SetEnvironmentVariable("VSCE_PAT", "new-token-value", "User")
# Restart terminal to pick up changes
Prevention: Calendar Reminders
Set calendar reminders before token expiry:
Token: VSCE_PAT
Created: 2026-01-15
Expires: 2026-04-15
Reminder: 2026-04-01 (2 weeks before)
Token Scope Requirements
VS Code Marketplace (VSCE)
Required scopes for Azure DevOps PAT:
- Marketplace: Manage (or Publish)
- Organization: All accessible organizations (or specific)
npm
Required scope:
- Automation (for CI/CD) or Publish (for interactive)
GitHub Packages
Required scopes:
write:packages
read:packages
delete:packages (if needed)
CI/CD Secret Rotation
For GitHub Actions secrets:
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
Reminder: When you rotate a token, update:
- Local environment variable
- CI/CD secrets (GitHub, Azure DevOps, etc.)
- Any shared credential stores
Verification Checklist
Common Symptoms
- 401 Unauthorized during
vsce publish
- 401 during
npm publish
- "Authentication failed" with no further details
- Worked last month, fails now (no code changes)
Preflight Script Idea
const { execSync } = require('child_process');
function checkVscePat() {
const pat = process.env.VSCE_PAT;
if (!pat) {
console.error('VSCE_PAT not set');
process.exit(1);
}
if (pat.length < 50) {
console.warn('VSCE_PAT looks short - might be truncated or invalid');
}
console.log('VSCE_PAT is set. If publish fails with 401, check token expiry.');
}
Related Skills
node-winget-collision — Windows Node.js issues