
Description
Diagnose a Meta access token problem (expired, wrong scopes, wrong app, invalid) WITHOUT the token ever entering the agent or AI provider context. Guides the developer to inspect the token themselves via the Access Token Debugger web tool or the public debug_token Graph API, then interprets the returned metadata. Use when an API call fails with an auth/OAuthException error (e.g. code 190) or a token isn't behaving as expected.
SKILL.md
Debug Access Token
Help a developer figure out why a Meta access token is failing — without ever handling the raw token yourself.
Security first — never handle a live token
An access token is a bearer credential: whoever holds it can act as its owner. Anything pasted into this chat enters the agent's context and is transmitted to the AI provider (logs, history, retention). Treat a token like a password.
- Do NOT ask the developer to paste an access token (or an app secret) into this chat. Inspect tokens using the developer-run options below, and ask only for the resulting metadata.
- If a token was already pasted, tell the developer to revoke/rotate it (Graph API Explorer, or the app dashboard → regenerate), then continue with the metadata flow below using a fresh token.
Workflow
- Confirm the symptom. Ask what failed:
- The error
codeandsubcode(e.g.190/463) - Which endpoint/request failed
- Which app the call was made with, and what the token is expected to do (which permissions/scopes)
- The error
- Have the developer inspect the token themselves. Offer either option — both run in the developer's own environment and return only metadata, never routing the token through this agent:
- A. Access Token Debugger (web): open https://developers.facebook.com/tools/debug/accesstoken/, paste the token there (a Meta first-party surface, not this agent), and read the results panel.
- B.
debug_tokenGraph API via the bundled script: this skill ships a ready-to-run script,scripts/debug_token_probe.py, that reads the token and app secret from environment variables (by name — never their values) and prints only redacted metadata; the developer sets the env vars and runs it in their own shell, then brings back only the printed JSON. See the Using thedebug_tokenscript section below for how to run it and the expected output. Reference: debug_token docs. Never ask the developer to send you the token or the app secret.
If the developer needs exact, current steps, usedevtools_discovery(actionsearch_docs) to fetch the latest Access Token Debugger /debug_tokendocumentation. - Ask only for the redacted metadata. Request they copy back the debug output with PII removed. Keep:
is_valid,type,app_id,application,issued_at,expires_at,data_access_expires_at,scopes/granular_scopes, and anyerror.code/error.subcode/error.message. Tell them to redactuser_idand any profile IDs — you do not need them to diagnose the failure. (The bundled script already emits only this allow-listed, redacted subset.) See Using thedebug_tokenscript below for an example of the token-free output to expect. - Interpret the metadata and report (format below).
Using the debug_token script (Option B)
When the developer prefers the API over the web debugger, point them at the script
bundled with this skill, scripts/debug_token_probe.py. It reads the credentials
from environment variables in the developer's own shell — by name, never
their values — so no token or secret ever appears in the chat, in a script you
author, or on a command line. The shell provides the values at run time, and the
script prints only redacted metadata. Do not re-derive or paste the script into the
chat; it is already checked in and vetted — just tell the developer how to run it.
Give the developer the absolute path. The script lives inside the installed
plugin, not in the developer's working directory, so a relative path will not
resolve for them. Substitute the absolute path of this skill's directory — you know
it, having just read SKILL.md from there — wherever <skill-dir> appears below.
Have them run this in a throwaway shell, not the shell they start their agent from: an exported variable is inherited by every process that shell launches, so a token left exported can reach an agent started later from the same terminal.
Prompt for the two secrets. -s hides the input, so neither value is echoed to
the screen or typed on a command line. The prompt syntax differs by shell —
in zsh, read -p means "read from a coprocess", not "print this prompt", so the
bash form fails there:
# bash
read -rsp 'Access token: ' FB_INPUT_TOKEN; echo
read -rsp 'App secret: ' FB_APP_SECRET; echo
# zsh (the macOS default)
read -rs 'FB_INPUT_TOKEN?Access token: '; echo
read -rs 'FB_APP_SECRET?App secret: '; echo
Then, in either shell:
export FB_APP_ID='<your app id>'
export FB_INPUT_TOKEN FB_APP_SECRET
python3 <skill-dir>/scripts/debug_token_probe.py
unset FB_INPUT_TOKEN FB_APP_SECRET FB_APP_ID
The script needs only the Python 3 standard library — no packages to install. The
developer pastes back only the printed JSON. Example of the token-free output to
expect — note there is no token, no app secret, and no user_id; that is the
whole point:
{
"is_valid": true,
"type": "USER",
"app_id": "1234567890123456",
"application": "Example App",
"issued_at": 1785000000,
"expires_at": 1792800000,
"data_access_expires_at": 1800000000,
"scopes": ["public_profile", "email", "pages_show_list", "pages_read_engagement"]
}
Interpretation & Report Format
Token summary
- Valid? Token
type(User / Page / App / System User)? - Owning app: does
app_idmatch the app the call was made with? - Expiry:
expires_atin the past → expired;0→ never expires;data_access_expires_atin the past → data-access window lapsed (re-auth needed). - Scopes present vs. the scopes the failing call requires.
Diagnosis (common cases)
| Signal | Meaning | Fix |
|---|---|---|
is_valid=false, error 190 subcode 463 | Session expired | Re-authenticate the user |
is_valid=false, error 190 (no subcode) | Invalid or revoked token | Re-issue the token |
expires_at in the past | Expired short-lived token | Exchange for a long-lived token, or re-login |
Required scope missing from scopes | Permission not granted/approved | Request the scope; run App Review (/app-review-prep) |
app_id ≠ the calling app | Token minted for a different app | Use a token issued by the correct app |
type not what the endpoint expects (User vs Page vs App) | Wrong token type | Mint the correct token type for that endpoint |
Next steps
- Concrete remediation for the diagnosed cause, then cross-links (below).
Acceptable vs unacceptable usage
- ✅ Interpreting redacted
debug_tokenmetadata the developer brings back - ✅ Linking the developer to the web Access Token Debugger
- ✅ Pointing the developer to the bundled
scripts/debug_token_probe.py(reads the token/app secret from environment variables by name) for them to run themselves - ✅ Emitting a command that references the credentials by environment-variable
name only (
"$FB_INPUT_TOKEN"), for the developer to run in their own shell - ❌ Accepting a raw or live access token as chat input
- ❌ Asking for an app secret
- ❌ Echoing a token back, or storing a token anywhere
- ❌ Emitting a command containing a literal token or app secret — including a
placeholder the developer substitutes. The value would land in their shell
history and, for the life of the process, in
psoutput - ❌ Running the
read/exportcommands or the script yourself. The developer runs them in their own shell; you never hold the credential
Tips
- Error code
190is the catch-allOAuthException; the subcode disambiguates it (463 = expired, 467 = invalid, etc.). Always ask for the subcode. - If the developer can't run
debug_token, the web Access Token Debugger needs no setup — start there. - Related:
/api-integration(token types & auth setup) and/api-health(rate limits/quota, once the token works).
More skills from the agentic-tools repository
View all 9 skillsapi-health
monitor API health for Meta apps
Aug 9API DevelopmentMonitoringObservabilityapi-integration
set up Meta API integrations
Aug 9API DevelopmentDocumentationIntegrationsapp-health-check
audit Meta app health and compliance
Aug 9AuditComplianceObservabilitySecurityapp-review-prep
prepare Meta apps for App Review
Aug 9ComplianceDeploymentOperationscompliance-check
check compliance status for Meta apps
Aug 9AuditComplianceRegulatory ComplianceSecuritydebug-webhooks
troubleshoot Meta app webhooks
Aug 9API DevelopmentDebuggingWebhooks
More from Meta Open Source
View publisherrelay-best-practices
write idiomatic Relay code
relay
Apr 22EngineeringFrontendGraphQLReact +1relay-performance
optimize Relay application performance
relay
Jun 10FrontendGraphQLPerformanceReact +1add-shape-types-to-torch-model
annotate PyTorch models with tensor shapes
pyrefly
Jul 18Data ModelingDeep LearningPythonPyTorchcamera-streaming
configure camera streaming and photo capture
meta-wearables-dat-ios
Aug 6CameraHardwareiOSVideodat-conventions
develop iOS applications with DAT SDK
meta-wearables-dat-ios
Aug 6iOSMobileSDKSwiftdebugging
debug wearable device software
meta-wearables-dat-ios
Aug 6DebuggingEngineeringiOS