affaan-m/ECC · error · Exception
Forbidden
Error message
Forbidden: {resp.json().get('detail', 'check permissions')} What it means
Posting pattern in the x-api skill: the API returned 403, meaning the app lacks permission for the action (wrong app tier, missing scopes, or read-only credentials); the API's detail field is surfaced with a fallback hint.
Solutions
- Provide valid credentials/configuration or wait for the rate-limit reset; verify permissions/role.
Defensive patterns
Strategy: fallback
When it happens
Trigger: Triggered when SKILL.md rejects the current invocation: Forbidden: <value>
Common situations: Occurs while running skills/x-api/SKILL.md with invalid arguments, missing flags, or a failing external dependency; the guard at skills/x-api/SKILL.md:206 aborts the command with this message.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
AI-assisted analysis of affaan-m/ECC@06c5e118c4 (2026-08-18).
Data as JSON: /api/errors/efdb51ef478f6a37.
Report an issue: GitHub.
Appendix: source
Thrown at skills/x-api/SKILL.md:206
remaining = int(resp.headers.get("x-rate-limit-remaining", 0))
if remaining < 5:
reset = int(resp.headers.get("x-rate-limit-reset", 0))
wait = max(0, reset - int(time.time()))
print(f"Rate limit approaching. Resets in {wait}s")
```
## Error Handling
```python
resp = oauth.post("https://api.x.com/2/tweets", json={"text": content})
if resp.status_code == 201:
return resp.json()["data"]["id"]
elif resp.status_code == 429:
reset = int(resp.headers["x-rate-limit-reset"])
raise Exception(f"Rate limited. Resets at {reset}")
elif resp.status_code == 403:
raise Exception(f"Forbidden: {resp.json().get('detail', 'check permissions')}")
else:
raise Exception(f"X API error {resp.status_code}: {resp.text}")
```
## Security
- **Never hardcode tokens.** Use environment variables or `.env` files.
- **Never commit `.env` files.** Add to `.gitignore`.
- **Rotate tokens** if exposed. Regenerate at developer.x.com.
- **Use read-only tokens** when write access is not needed.
- **Store OAuth secrets securely** — not in source code or logs.
## Integration with Content Engine
Use `brand-voice` plus `content-engine` to generate platform-native content, then post via X API:
1. Pull recent original posts when voice matching matters
2. Build or reuse a `VOICE PROFILE`
3. Generate content with `content-engine` in X-native formatView on GitHub (pinned to 06c5e118c4)