Claude-skill-registry linear-common-errors
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/linear-common-errors" ~/.claude/skills/majiayu000-claude-skill-registry-linear-common-errors && rm -rf "$T"
manifest:
skills/data/linear-common-errors/SKILL.mdsource content
Linear Common Errors
Overview
Quick reference for diagnosing and resolving common Linear API errors.
Prerequisites
- Linear SDK or API access configured
- Access to application logs
- Understanding of HTTP status codes
Error Categories
Authentication Errors (401/403)
Invalid API Key
Error: Authentication required Code: UNAUTHENTICATED
Causes:
- API key is invalid, expired, or revoked
- Key format is incorrect (should start with
)lin_api_ - Environment variable not loaded
Solutions:
// Verify key format const apiKey = process.env.LINEAR_API_KEY; if (!apiKey?.startsWith("lin_api_")) { console.error("Invalid API key format"); } // Test authentication const client = new LinearClient({ apiKey }); try { await client.viewer; console.log("Authentication successful"); } catch (e) { console.error("Authentication failed:", e); }
Permission Denied
Error: You don't have permission to access this resource Code: FORBIDDEN
Causes:
- API key doesn't have required scope
- User not a member of the team/organization
- Resource belongs to different workspace
Solutions:
- Check API key permissions in Linear Settings > API
- Verify team membership
- Regenerate key with correct permissions
Rate Limiting Errors (429)
Error: Rate limit exceeded Code: RATE_LIMITED Headers: X-RateLimit-Remaining: 0, Retry-After: 60
Causes:
- Too many requests in time window
- Burst of requests without throttling
Solutions:
// Implement exponential backoff async function withRetry<T>( fn: () => Promise<T>, maxRetries = 3 ): Promise<T> { for (let i = 0; i < maxRetries; i++) { try { return await fn(); } catch (error: any) { if (error?.extensions?.code === "RATE_LIMITED" && i < maxRetries - 1) { const delay = Math.pow(2, i) * 1000; console.log(`Rate limited, retrying in ${delay}ms...`); await new Promise(r => setTimeout(r, delay)); continue; } throw error; } } throw new Error("Max retries exceeded"); }
Validation Errors (400)
Error: Variable "$input" got invalid value Code: BAD_USER_INPUT
Common Validation Failures:
| Field | Error | Fix |
|---|---|---|
| "Team not found" | Verify team exists and accessible |
| "Invalid priority" | Use 0-4 (0=None, 1=Urgent, 4=Low) |
| "Invalid estimate" | Use team's configured values |
| "State not found" | State must belong to same team |
| "User not found" | User must be team member |
Debug Validation:
async function createIssueWithValidation(input: { teamId: string; title: string; stateId?: string; assigneeId?: string; }) { // Validate team exists const team = await client.team(input.teamId); if (!team) throw new Error(`Team not found: ${input.teamId}`); // Validate state belongs to team if (input.stateId) { const states = await team.states(); if (!states.nodes.find(s => s.id === input.stateId)) { throw new Error(`State ${input.stateId} not in team ${team.key}`); } } // Validate assignee is team member if (input.assigneeId) { const members = await team.members(); if (!members.nodes.find(m => m.id === input.assigneeId)) { throw new Error(`User ${input.assigneeId} not in team ${team.key}`); } } return client.createIssue(input); }
GraphQL Errors
Error: Cannot query field "nonExistent" on type "Issue" Code: GRAPHQL_VALIDATION_FAILED
Causes:
- Field name typo
- Querying deprecated field
- SDK version mismatch with API
Solutions:
# Update SDK to latest npm update @linear/sdk # Check API schema curl -H "Authorization: $LINEAR_API_KEY" \ https://api.linear.app/graphql \ -d '{"query": "{ __schema { types { name } } }"}'
Network Errors
Error: fetch failed Cause: ECONNREFUSED / ETIMEDOUT
Solutions:
// Add timeout and retry const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 30000); try { const response = await fetch("https://api.linear.app/graphql", { signal: controller.signal, // ... other options }); } finally { clearTimeout(timeout); }
Diagnostic Commands
Test API Connection
curl -s -H "Authorization: $LINEAR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query": "{ viewer { name email } }"}' \ https://api.linear.app/graphql | jq
Check Rate Limit Status
curl -I -H "Authorization: $LINEAR_API_KEY" \ https://api.linear.app/graphql # Look for: X-RateLimit-Limit, X-RateLimit-Remaining
Validate Webhook Signature
import crypto from "crypto"; function verifyWebhookSignature( body: string, signature: string, secret: string ): boolean { const hmac = crypto.createHmac("sha256", secret); const digest = hmac.update(body).digest("hex"); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(digest) ); }
Error Handling Pattern
import { LinearClient, LinearError } from "@linear/sdk"; async function safeLinearCall<T>( operation: () => Promise<T>, context: string ): Promise<T> { try { return await operation(); } catch (error) { if (error instanceof LinearError) { console.error(`Linear API Error in ${context}:`, { message: error.message, type: error.type, errors: error.errors, }); // Handle specific error types switch (error.type) { case "AuthenticationError": throw new Error("Please check your Linear API key"); case "RateLimitedError": throw new Error("Too many requests, please retry later"); default: throw error; } } throw error; } }
Resources
Next Steps
Set up comprehensive debugging with
linear-debug-bundle.