
Insforge Debug
- 20k installs
- 33 repo stars
- Updated July 27, 2026
- insforge/agent-skills
insforge-debug is an agent skill that >-.
About
>- --- name: insforge-debug description: >- Use when diagnosing problems in an InsForge project - reactive failures (SDK error object, HTTP 4xx/5xx, gateway timeout 502/503/504, edge function failure or timeout, login/OAuth/auth errors, RLS denial, realtime channel issues, slow query on one endpoint, edge function or Vercel deploy failure), proactive audits (security/RLS review, performance/index review, system health check, pre-launch readiness), or when the user has an error but doesn't know where to start. license: MIT metadata: author: insforge version: "2.0.0" organization: InsForge date: May 2026 --- # InsForge Debug Diagnose problems in InsForge projects by combining the backend's observability primitives - logs, metrics, db-health, advisor, policies, metadata, error objects, deploy state, and AI assist. A reference per **debug primitive** (one observability surface each - under `references/`) 2. **Symptom Recipes** (below) that name the primitive sequence for known reactive symptoms and proactive audits **Always use `npx @insforge/cli`** - never install the CLI globally.
- A reference per **debug primitive** (one observability surface each - under `references/`)
- **Symptom Recipes** (below) that name the primitive sequence for known reactive symptoms and proactive audits
- **error-objects** - read code/message/details. If code starts with `PGRST*`, route by prefix using the table in the re
- **logs** (matching source per error-objects routing) - find the error timestamp, get the full backend-side context.
- **db-health** (`connections`, `locks`, `slow-queries`) - only if the error suggests DB issue (PostgREST timeout, lock
Insforge Debug by the numbers
- 19,973 all-time installs (skills.sh)
- +3,082 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #31 of 2,184 Testing & QA skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
insforge-debug capabilities & compatibility
- Capabilities
- a reference per **debug primitive** (one observa · **symptom recipes** (below) that name the primit · **error objects** — read code/message/details. i · **logs** (matching source per error objects rout · **db health** (`connections`, `locks`, `slow que
- Use cases
- documentation
What insforge-debug says it does
A reference per **debug primitive** (one observability surface each — under `references/`) 2.
**Symptom Recipes** (below) that name the primitive sequence for known reactive symptoms and proactive audits **Always use `npx @insforge/cli`** — never install the CLI globally.
## Fastest Path: AI-Assisted Triage When the user gives a concrete description (error message, failing URL, HTTP status), hand it to the InsForge debug agent.
Unlike the other primitives, this one returns suggestions, not just observations — verify the diagnosis against the primitives it cites before acting on it.
npx skills add https://github.com/insforge/agent-skills --skill insforge-debugAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 20k |
|---|---|
| repo stars | ★ 33 |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 27, 2026 |
| Repository | insforge/agent-skills ↗ |
What problem does insforge-debug solve for developers using this skill?
>-
Who is it for?
Developers who need insforge-debug patterns described in the cached skill documentation.
Skip if: Skip when docs are empty or the task is outside the skill's documented scope.
When should I use this skill?
>-
What you get
Actionable workflows and conventions from SKILL.md for insforge-debug.
- root-cause report
- remediation steps
- audit checklist results
By the numbers
- Skill version 2.0.0 in metadata
- Covers gateway status codes 502, 503, and 504 explicitly
Files
InsForge Debug
Diagnose problems in InsForge projects by combining the backend's observability primitives — logs, metrics, db-health, advisor, policies, metadata, error objects, deploy state, and AI assist. This skill provides:
1. A reference per debug primitive (one observability surface each — under references/) 2. Symptom Recipes (below) that name the primitive sequence for known reactive symptoms and proactive audits
Always use `npx @insforge/cli` — never install the CLI globally.
Fastest Path: AI-Assisted Triage
When the user gives a concrete description (error message, failing URL, HTTP status), hand it to the InsForge debug agent. Unlike the other primitives, this one returns suggestions, not just observations — verify the diagnosis against the primitives it cites before acting on it.
npx @insforge/cli diagnose --ai "<issue description>"See references/ai-assisted.md for when to use this first vs when to skip, and how to verify the output.
Debug Primitives
Each primitive is one independently-queryable observability surface backed by a distinct underlying data source. Real diagnoses are compositions of primitives.
All commands run via npx @insforge/cli .... The (command) shown next to each primitive is the actual CLI command — primitive names are concept labels, not CLI subcommand names (e.g., "DB health" is diagnose db, not diagnose db-health; "Policies" is db policies, not diagnose policies).
| Primitive (command) | What you see | Reference |
|---|---|---|
Logs (logs <source>; diagnose logs for cross-source aggregate) | Time-stream of events from 5 backend sources (insforge.logs / postgREST.logs / postgres.logs / function.logs / function-deploy.logs) | references/logs.md |
Metrics (diagnose metrics) | EC2 instance time-series (CPU / memory / disk / network) over 1h / 6h / 24h / 7d | references/metrics.md |
DB health (diagnose db) | Current Postgres state via 7 named checks (connections / slow-queries / bloat / size / index-usage / locks / cache-hit) | references/db-health.md |
Advisor (diagnose advisor --json) | Static-scan issues across 3 categories (security / performance / health) with ruleId / affectedObject / recommendation | references/advisor.md |
Policies (db policies) | Active RLS rules from pg_policies (USING / WITH CHECK per cmd per role) — returns all policies as a dump | references/policies.md |
Metadata (metadata --json) | Declarative backend state dump (auth config / tables / buckets / functions / AI models / realtime channels) | references/metadata.md |
| Error objects (no command — read SDK / HTTP response) | SDK error envelope + HTTP status — the routing table from a client-visible error to the right log source | references/error-objects.md |
Deploy state (deployments list + deployments status <id> --json + logs function-deploy.logs) | Frontend (Vercel) deployment history + per-deploy metadata, plus edge function deploy logs | references/deploy-state.md |
AI assist (diagnose --ai "<description>") | LLM agent that combines the other primitives — returns a diagnosis with suggestions | references/ai-assisted.md |
Symptom Recipes
Each recipe is a primitive call sequence with one-line "look for X" at each step. Command syntax, flags, and deep interpretation are in the per-primitive references above.
Recipe: SDK returned { data: null, error: { code, message } }
1. error-objects — read code/message/details. If code starts with PGRST*, route by prefix using the table in the reference. 2. logs (matching source per error-objects routing) — find the error timestamp, get the full backend-side context. 3. db-health (connections, locks, slow-queries) — only if the error suggests DB issue (PostgREST timeout, lock conflict).
Recipe: HTTP 4xx/5xx response on a specific request
1. error-objects — use the HTTP status routing table to pick the log source (each status has a distinct path; 429 is special). 2. logs (right source for that status) — find the failing request line and error. 3. metrics — only for 5xx patterns spanning multiple endpoints, to confirm system-wide load issue.
Recipe: RLS access issue (403 on write, or empty result on read)
Same bug, two surfacings. Writes (INSERT / UPDATE / DELETE) fail loudly with 403. Reads (SELECT) fail silently with an empty array — PostgREST filters denied rows out instead of returning 403, so the request looks successful with zero rows. Diagnosis path is the same except step 1 only applies to the 403 variant.
1. logs (postgREST.logs) — 403 variant only: find the policy violation event with table and role context. Empty-result variant: skip — no error is logged for silently-filtered rows. 2. policies — list policies for that table; walk USING / WITH CHECK against the actual request and the JWT claim used. 3. metadata — verify auth config (which claim feeds auth.uid() / requesting_user_id(); for third-party auth like Clerk/Auth0, is the provider registered as a JWT issuer?). 4. db query (db query "<sql>") — empty-result variant only: confirm rows that should be visible actually exist by querying as service role (not as the user): npx @insforge/cli db query "SELECT id, user_id FROM <table>". Distinguishes "RLS filtered everything" from "no matching data exists".
Recipe: Login fails / OAuth callback errors / token expired
1. logs (insforge.logs) — find auth errors with timestamp and provider context. 2. metadata — verify the provider is enabled, redirect URLs match the callback URL exactly (protocol + host + path).
Recipe: Edge function runtime error / timeout
1. logs (function.logs) — get the error stack and execution context. 2. metadata — confirm the function exists and status: "active". 3. (If needed) npx @insforge/cli functions code <slug> — inspect the source for obvious issues.
Recipe: functions deploy failed
1. deploy-state (function-deploy.logs) — find the build/push error. 2. metadata — confirm whether the function ended up in the active list (partial-deploy detection).
Recipe: deployments deploy failed (Vercel)
1. deploy-state (deployments list + status <id> --json) — read status, metadata.webhookEventType, and envVarKeys. 2. Local npm run build — reproduce the same error locally for faster iteration.
Recipe: Single slow query / one endpoint slow
1. logs (postgres.logs) — find the query text and timestamp. 2. db-health (slow-queries, index-usage) — confirm it's in pg_stat_statements; check for missing index. 3. policies — if it's an RLS-gated table, verify the policy isn't adding hidden joins.
Recipe: All responses slow / high CPU/memory (active incident)
1. metrics (--range 1h) — confirm system-wide pressure (CPU / memory / disk). 2. db-health — DB is the most common bottleneck; check connections, locks, slow-queries. 3. logs (diagnose logs aggregate) — error patterns across sources at the spike timestamp. 4. advisor (--severity critical) — pre-existing known issues that may explain the degradation.
Recipe: Realtime channel won't connect / messages missing
1. logs (insforge.logs) — WebSocket errors and subscription failures. 2. metadata — verify the channel pattern matches what the client subscribes to, enabled: true. 3. policies — RLS on the underlying table (realtime delivers row changes; RLS gates which rows the subscriber sees).
Recipe: 429 rate limit
1. error-objects — confirm 429 status. No logs are recorded for 429s; no `Retry-After` header is returned. Don't waste time grepping logs. 2. metrics (--range 1h) — overall backend load context. 3. Fix is always client-side: debounce, batch, exponential backoff, eliminate retry loops.
Recipe: Gateway timeout (502 / 503 / 504) on a specific URL
Route by URL subsystem before drilling:
| URL pattern | Drill into |
|---|---|
/api/database/records/... | logs (postgREST.logs → postgres.logs) + db-health (locks, slow-queries) |
/functions/<slug> | logs (function.logs) — function may be crash-looping |
/api/auth/... | logs (insforge.logs) |
| Any path during system-wide spike | metrics (--range 1h) |
Recipe: Pre-launch / proactive audit
Requires Platform login (npx @insforge/cli login). Not available when the project is linked via `--api-key` — fall back todb-health+policies+metadatafor a manual audit in that case.
1. advisor — full scan, then --severity critical first, then warnings. 2. advisor (--category security) — focus on security issues; cross-verify with policies (RLS coverage) and metadata (auth config, public buckets, secret presence). 3. advisor (--category performance) — cross-verify with db-health (slow-queries, index-usage, bloat). 4. advisor (--category health) — cross-verify with metrics (resource trends over 7d). 5. After fixes, re-run advisor and confirm isResolved: true for each addressed ruleId.
Recipe: Don't know where to start
1. ai-assisted (diagnose --ai "<error or URL>") — get a starting hypothesis. 2. Verify by re-checking the primitives the diagnosis names. Trust the primitive observations over the suggestion.
Advisor
Static-scan engine that audits the project against a rule catalog and returns issue rows. The primary primitive for proactive audits — security misconfigurations, performance regressions, and system health concerns surfaced without a specific failing request.
Command
npx @insforge/cli diagnose advisor [--severity critical|warning|info] [--category security|performance|health] [--limit <n>] [--json]Default limit: 50. Requires Platform login — not available on backends linked via `--api-key`.
Add `--json` when you need the full issue payload. Human-readable output is a 4-column table (severity / category / affectedObject / title). Fields like ruleId, description, recommendation, isResolved are only emitted by --json — without the flag, you can't read or act on the recommendation programmatically.
What you see
Each scan returns:
Scan summary — scanId, scannedAt, status, and counts by severity (critical / warning / info).
Issue rows — each issue has:
| Field | Meaning |
|---|---|
ruleId | Stable identifier of the rule that fired (e.g., security.rls.missing-policy) |
severity | critical / warning / info |
category | security / performance / health |
affectedObject | The specific schema object (table, function, policy, secret name) the issue applies to |
title | Short human label |
description | What the rule detected |
recommendation | Suggested fix, often a concrete SQL/CLI step |
isResolved | true after a re-scan confirms the fix |
Categories
| Category | Typical rules | Fix in |
|---|---|---|
security | RLS missing/permissive on a table, expired/exposed secrets, weak JWT config, public bucket on sensitive data | db migrations (RLS), secrets (key rotation), metadata (auth/bucket config) |
performance | Missing index on heavy filter column, bloat over threshold, sequential scans on large tables, slow recurring query | db migrations (indexes), query rewrite, vacuum tuning |
health | Connection pool near limit, EC2 disk filling, deprecated feature in use, version drift | Infra resize, code change, version upgrade |
How to read
1. Start with severity: --severity critical first; critical issues block launch. 2. Group by category to keep the fix mode coherent (don't context-switch between RLS edits and index migrations). 3. `affectedObject` tells you where to fix — it names the concrete schema object. 4. `recommendation` is usually actionable as-is. Verify it makes sense (the recommendation may be generic), then apply via the appropriate primitive's tooling.
Iteration workflow
1. Scan: diagnose advisor --severity critical --json
2. Triage: pick one issue, read affectedObject + recommendation
3. Verify: inspect the affected object (db query / db policies / metadata)
4. Fix: apply the change (migration / RLS edit / secret rotation / config update)
5. Re-scan: diagnose advisor --json — confirm isResolved=true for that ruleId
6. Repeat with next critical, then warnings, then infoBoundaries
- Scans are not real-time. A new scan triggers when the platform schedules it; recommendations lag behind very recent changes. Force a fresh scan if needed.
- Recommendations are static suggestions, not auto-fixes. Always validate against current schema state before applying.
- `affectedObject` is a string, not a typed reference. It names the object but doesn't link to it — combine with metadata / policies to inspect.
- Not available when linked via `--api-key`. Requires
insforge login(Platform auth).
Example
Pre-launch audit:
# Full scan, critical only first
npx @insforge/cli diagnose advisor --severity critical
# Security focus
npx @insforge/cli diagnose advisor --category security
# Performance focus (often pairs with db-health to verify)
npx @insforge/cli diagnose advisor --category performance
npx @insforge/cli diagnose db --check slow-queries,index-usage
# Re-scan after fixes
npx @insforge/cli diagnose advisor --severity criticalFrequently paired with
- policies — security category issues often name a table with missing/broken RLS policy
- metadata — security/health issues often name a configured object (bucket, secret, auth provider) whose state needs inspecting
- db-health — performance category overlaps with
slow-queries/index-usage/bloat; cross-verify - metrics — health category issues (pool exhaustion, disk fill) line up with metric trends
AI assist
The meta-primitive: hand a natural-language problem description to a backend-side LLM agent that combines the other primitives (logs, metrics, db-health, advisor, policies, metadata) on its own and returns a diagnosis plus suggested solutions.
Unlike every other primitive in this skill, `diagnose --ai` returns suggestions, not just observations. Verify before acting.
Command
npx @insforge/cli diagnose --ai "<issue description>"The description should include: the error / failing URL / HTTP status / function slug — whatever concrete signal the user has.
When to use first
- User pasted an error, request URL, or status code and asks "why?"
- You want a fast first pass before deciding which primitive to drill into
- The problem spans multiple subsystems (frontend + backend + database) and the right starting primitive isn't obvious
When to skip
- The symptom clearly maps to one primitive (e.g., "Vercel deploy failed" → go straight to deploy-state)
- You're doing a proactive audit (no concrete error — that's advisor)
- You already know exactly which log source has the error
How to verify the output
The agent's diagnosis names primitives and observations. Re-check each:
| If the diagnosis says... | Verify with... |
|---|---|
| "An RLS policy is blocking the request" | policies — read the actual policy on that table |
| "Slow query on table X" | db-health slow-queries + logs postgres.logs for the actual query |
| "Function is timing out" | logs function.logs — read the actual timeout/error stack |
| "Connection pool exhausted" | db-health connections — confirm the count and idle-in-transaction state |
| "Missing index on column Y" | db-health index-usage + advisor performance — both should agree |
If the verification disagrees with the diagnosis, trust the primitive observation, not the suggestion. Suggestions can be plausible-sounding but wrong (LLM may pattern-match on similar errors); raw pg_stat numbers and log lines can't lie.
Boundaries
- Returns suggestions, not just data. Different from every other primitive — treat the output as a starting hypothesis, not a verdict.
- Doesn't replace [advisor](advisor.md). Advisor surfaces issues based on a static rule catalog;
--aireasons about a specific reported symptom. They serve different goals. - Consumes the other primitives. When this fails or seems off, fall back to the primitives directly.
Example
User pastes: "I invoked https://kttprzh4.functions.insforge.app/newton and got 508: Loop Detected (LOOP_DETECTED). Recursive requests to the same deployment cannot be processed."
npx @insforge/cli diagnose --ai "I invoked edge function https://kttprzh4.functions.insforge.app/newton, got error: 508: Loop Detected (LOOP_DETECTED)\n\nRecursive requests to the same deployment cannot be processed."Read the diagnosis and suggestions, then verify with:
# Verify with function logs
npx @insforge/cli logs function.logs --limit 50
# Verify the function code doesn't actually call itself
npx @insforge/cli functions code newtonFrequently paired with
- All other primitives —
--aiconsumes them and you verify back against them. Treat AI assist as a router that points at primitives; the primitives are the ground truth.
DB health
Postgres system views (pg_stat_*, pg_locks, pg_class) exposed as named checks. The primary primitive for current database state — connection pool, query performance, lock contention, storage, index efficacy.
Command
npx @insforge/cli diagnose db [--check <checks>]--check accepts comma-separated names. Default all. Run no-arg first when triaging unknown DB issues.
Checks
| Check | Underlying view | What it tells you |
|---|---|---|
connections | pg_stat_activity | Active vs idle vs idle-in-transaction count; how close to pool limit |
slow-queries | pg_stat_statements | Queries by total/mean exec time; which queries dominate load |
bloat | pg_class, pg_stats | Table/index dead-row bloat (vacuum lag, write-heavy tables) |
size | pg_class size functions | Table and index disk footprint |
index-usage | pg_stat_user_indexes | Indexes that are never scanned (unused) vs heavy hitters |
locks | pg_locks + pg_stat_activity | Lock contention, blocking queries, deadlock candidates |
cache-hit | pg_statio_* | Buffer cache hit ratio (low = working set exceeds RAM) |
How to read
| Reading | Likely problem | Next step |
|---|---|---|
connections near pool limit + many idle-in-transaction | Connection leak in client code | Find client missing release() or transaction not committing |
slow-queries top entry called frequently | Missing index or bad plan | Check index-usage for that table; consider migration |
bloat high on actively-written table | Vacuum not keeping up | Schedule vacuum tighter or rewrite query pattern |
index-usage shows unused indexes | Wasted write cost | Drop unused indexes (after confirming they're truly unused) |
locks with blocker/blocked pairs | Long transactions or deadlocks | Kill blocking PID after investigation, fix the lock-holding query |
cache-hit < 0.99 | Working set exceeds RAM | Tune queries to reduce buffer churn, or scale |
Boundaries
- Current snapshot, not history.
pg_stat_*resets on Postgres restart; numbers are cumulative since last reset, not a time series. - Doesn't show query text inline.
slow-queriesshows hashed query templates — get the actual SQL from logs (postgres.logs) orpg_stat_statements.querydirectly viadb query. - Doesn't evaluate RLS. For "which policy is making this query slow," use policies.
Example
User reports: "this one query is slow — SELECT * FROM orders WHERE user_id = ... ORDER BY created_at DESC".
# 1. Confirm it's in the slow-query log and check index usage on the table
npx @insforge/cli diagnose db --check slow-queries,index-usage
# 2. Verify no lock contention from a concurrent writer
npx @insforge/cli diagnose db --check locks
# 3. Cross-reference postgres.logs for the actual query plan / errors
npx @insforge/cli logs postgres.logs --limit 100Frequently paired with
- logs —
postgres.logshas the query text, plans, and error context behindslow-queries/locksaggregates - policies — when slow queries are RLS-gated, the policy may be adding hidden joins
- metrics — DB pressure usually shows as EC2 CPU/memory pressure; cross-reference timestamps
- advisor — performance category often pre-flags the same issues
slow-queries/index-usagewould surface
Deploy state
History and per-deploy metadata for both frontend deployments (Vercel) and edge function deploys. The primary primitive for debugging what happened during a deploy — separate from runtime logs because deploy failures often never leave a runtime trace.
Commands
# Frontend (Vercel)
npx @insforge/cli deployments list
npx @insforge/cli deployments status <id> [--sync] [--json]
# Edge function deploys
npx @insforge/cli logs function-deploy.logs [--limit <n>]
npx @insforge/cli functions listFrontend deployments
deployments list returns recent deploys with status. deployments status <id> --json returns per-deploy metadata:
| Field | Meaning |
|---|---|
status | pending / building / ready / error / canceled |
metadata.target | Vercel deploy target (production / preview) |
metadata.fileCount | Number of files uploaded |
metadata.projectId | Vercel project ID |
metadata.startedAt | Build start time |
metadata.envVarKeys | Env var keys baked into the build (values redacted) |
metadata.webhookEventType | e.g., deployment.succeeded, deployment.error |
--sync re-fetches from Vercel (use when the local cached status looks stale).
Edge function deploys
function-deploy.logs captures backend deploy events (compile errors, push failures, registration errors). functions list confirms the final state — if the function isn't there or status != active, the deploy didn't fully take.
How to read
For "frontend deploy failed":
1. deployments list — find the failing deploy id 2. deployments status <id> --json — read status and the metadata block; webhookEventType usually names the failure stage 3. Reproduce locally: npm run build — server deploys often surface the same error that local build would (faster to debug locally) 4. Verify envVarKeys matches what the app needs at runtime
For "function deploy failed":
1. npx @insforge/cli logs function-deploy.logs --limit 50 — find the build/push error 2. npx @insforge/cli functions list — confirm the function did or didn't make it into the active list 3. Re-run npx @insforge/cli functions deploy <slug> if needed and capture stdout for the explicit error
Boundaries
- Doesn't surface Vercel build logs inline. Detailed Vercel build output lives in the Vercel dashboard or via
vercel logs; this primitive surfaces the deploy event metadata. - Doesn't include compute service (Fly) deploy errors. For compute services use
npx @insforge/cli compute events <id>(machine lifecycle); container stdout/stderr is not yet exposed. - Distinct from runtime errors. A function with a successful deploy can still error at invoke time — that's logs
function.logs, not this primitive.
Example
User reports: "I ran deployments deploy and got an error."
# 1. Get the most recent deploy id and status
npx @insforge/cli deployments list
# 2. Full metadata on the failed one
npx @insforge/cli deployments status <id> --json
# 3. Reproduce locally to see the actual build error
npm run buildUser reports: "functions deploy my-handler failed."
# 1. Re-run to capture the explicit error
npx @insforge/cli functions deploy my-handler
# 2. Backend-side deploy log
npx @insforge/cli logs function-deploy.logs --limit 50
# 3. Confirm the function isn't half-deployed
npx @insforge/cli functions listFrequently paired with
- logs —
function-deploy.logsis the source;function.logsis separate (runtime, not deploy) - metadata — verify the function ended up
activeafter deploy
Error objects
The error envelope returned by SDK calls and HTTP responses. The entry-point primitive — almost every reactive debug starts by reading the error and routing to the right log source / primitive.
This primitive isn't a command; it's the protocol for reading what the client got back, plus the routing tables that turn an error into "look here next."
SDK error envelope
const { data, error } = await client.database.from('posts').select('*')
// error: { code: string, message: string, details?: string }Read all three fields. code routes to the right log source; message and details provide context.
Error code → log source
| Code prefix | Source | Look in |
|---|---|---|
PGRST* (PostgREST errors: PGRST204, PGRST301, etc.) | PostgREST API layer | logs postgREST.logs |
SQL state codes (23505 unique violation, 42P01 undefined table, etc.) | Postgres | logs postgres.logs |
AUTH_* / OAuth errors | Backend auth | logs insforge.logs |
| Generic 500 / no code | Server error in backend | logs — start with diagnose logs aggregate, then drill |
HTTP status routing
| Status | What it means | Where to look |
|---|---|---|
| 400 | Request payload/params malformed | logs postgREST.logs for validation error |
| 401 | Auth token missing / invalid / expired | logs insforge.logs + metadata auth config |
| 403 | RLS policy or permission denied | logs postgREST.logs + policies + metadata |
| 404 | Endpoint or resource doesn't exist | metadata — verify the table/function/bucket exists |
| 429 | Rate limit hit | No logs — see 429 note below |
| 500 | Server-side error | logs diagnose logs (aggregate) → drill into specific source |
| 502 / 503 / 504 | Gateway / upstream timeout | Route by URL subsystem — see 5xx gateway note |
429 — special case
429 responses are not logged in any source and the backend does not return Retry-After or X-RateLimit-* headers. Checking logs is useless.
What to do:
1. Read the client code that issued the request. Look for: loops without throttling, missing debounce, retry-on-failure without exponential backoff, parallel calls that could be batched. 2. Check metrics for overall backend load context — is the system being slammed? 3. The fix is always client-side: reduce frequency, add backoff/debounce, batch operations.
5xx gateway timeout (502 / 503 / 504) — route by URL subsystem
The status alone doesn't tell you which subsystem timed out. Route by the URL path:
| URL pattern | Subsystem | Look in |
|---|---|---|
/api/database/records/... or /api/database/... | PostgREST → Postgres | logs postgREST.logs then postgres.logs; db-health locks, slow-queries |
/functions/<slug> | Edge function | logs function.logs; check function isn't crash-looping |
/api/auth/... | Auth backend | logs insforge.logs |
/api/storage/... | Storage | logs insforge.logs |
| Any path during a system-wide spike | EC2 saturation | metrics --range 1h |
Example
User pastes: POST /api/database/records/posts returned { code: "PGRST204", message: "Column not found" }.
1. Read code: PGRST* → PostgREST source. PGRST204 specifically means column not found — a select / columns / order / filter parameter references a column that doesn't exist on the table. 2. Read message / details to identify the offending column name. Verify the table schema with npx @insforge/cli db tables or npx @insforge/cli metadata --json. 3. Drop into postgREST.logs for the full error context if details is empty:
npx @insforge/cli logs postgREST.logs --limit 50Frequently paired with
- logs — every code routes to a log source for the actual error context
- policies — 403 always needs policy inspection
- metadata — 404 / config-related codes need metadata to confirm the configured state
- ai-assisted — when the code is unfamiliar or the error spans subsystems, hand it to
diagnose --ai
Logs
Time-stream of events emitted by each backend service. The primary primitive for finding when something failed and what the backend was doing at that moment.
Command
npx @insforge/cli logs <source> [--limit <n>]Default limit: 20. Source names are case-insensitive (postgrest.logs works the same as postgREST.logs).
Sources
| Source | What it contains | Reach for when |
|---|---|---|
insforge.logs | Main backend (auth, API gateway, realtime, edge function dispatcher, deploy controller) | Auth/OAuth errors, realtime WS errors, generic 5xx, signup/login failures |
postgREST.logs | PostgREST API layer (REST/CRUD over the database) | 400 (payload), 403 (RLS denied), PGRST* error codes |
postgres.logs | PostgreSQL itself | SQL errors, query warnings, slow query log, deadlock, constraint violations |
function.logs | Edge function execution (per-invocation runtime) | Function threw / timed out / unhandled rejection |
function-deploy.logs | Edge function deploy (build + push) | functions deploy failed; function isn't in functions list |
Cross-source aggregate
npx @insforge/cli diagnose logs [--source <name>] [--limit <n>]Aggregates error-level only rows across all sources. Use first when you don't know which source the error lives in.
How to read
Each line has timestamp + source + level + message. When chasing a known-time symptom:
1. Get the approximate timestamp from the user (when did the request fail?) 2. Increase --limit until the window covers it (start 50, bump to 200 if needed) 3. Look for the level (ERROR / WARN) and message — the message usually names the failing component
For request-correlated symptoms (single failing URL), look for the request line in postgREST.logs (REST calls) or insforge.logs (auth/realtime/function dispatch) — both include the URL path.
Boundaries
- Logs are streamed, not retained forever. If the user reports something from days ago, you may not find it. State this explicitly instead of guessing.
- 429 responses are NOT logged. Rate limit hits don't appear in any source — confirm via error-objects status code and check metrics for backend load context.
- `diagnose logs` filters to errors only. For warnings or info-level activity, query the specific source directly.
Example
User reports: POST /api/database/records/posts returned 500 around 14:32.
# Aggregate first to see if the error surfaces anywhere
npx @insforge/cli diagnose logs --limit 100
# If it's a CRUD path, postgREST is the likely source
npx @insforge/cli logs postgREST.logs --limit 100
# If postgREST log shows "SQL error", drop into postgres
npx @insforge/cli logs postgres.logs --limit 100Frequently paired with
- error-objects — start there to pick the right source from the error code/HTTP status
- db-health — when postgres.logs shows slow/locked queries, confirm with
pg_stat_* - policies — when postgREST.logs shows RLS denial, inspect which policy fired
- metadata — when logs show auth/function/channel errors, verify the configured state
Metadata
Declarative dump of the backend's configured state: auth provider config, database tables, storage buckets, edge functions, AI models, realtime channels. The primary primitive for what the project is set up to do — used to confirm configuration matches expectations, find misconfiguration, and detect drift.
Command
npx @insforge/cli metadata [--json]--json for structured output (preferred when extracting fields for follow-up commands).
What you see
| Section | Contains |
|---|---|
| Auth | Configured providers (email/password, OAuth providers, third-party JWT), JWT config, allowed redirect URLs |
| Database | Tables with schema (columns, types), indexes, triggers |
| Storage | Buckets with public flag and size limits |
| Functions | Edge functions with slug, status (active / inactive), runtime |
| AI | Configured models, OpenRouter key presence |
| Realtime | Channel patterns and enabled flag |
How to read
For "is this thing configured the way I think?":
| Symptom | Section to check | What to look for |
|---|---|---|
| OAuth callback errors | Auth | Provider enabled? Redirect URLs match the callback in the request? |
| 401 / token-expired everywhere | Auth | JWT secret rotation, third-party provider integration mismatch |
404 on /api/database/records/<name> | Database | Table exists in the dump? Spelling? |
| Storage upload silently public | Storage | Bucket public: true when it should be false |
| Edge function returns 404 | Functions | Function in list with status: "active"? |
functions deploy succeeded but invoke fails | Functions | Function status — may be inactive |
| Realtime channel "doesn't exist" | Realtime | Channel pattern matches what client subscribes to? enabled: true? |
Boundaries
- Configuration state, not runtime state. Tells you what's declared, not what's currently broken. A function with
status: activemay still be crashing on every invocation — pair with logs (function.logs). - Doesn't show RLS policies. For RLS use policies; metadata only confirms the table exists.
- Snapshot at query time. Just-applied migrations or deploys may not yet be reflected — wait a moment and re-query if you suspect staleness.
Example
User reports: "OAuth login with Google redirects but then errors out."
# 1. Pull current auth config
npx @insforge/cli metadata --json
# 2. In the auth section, confirm:
# - google provider enabled: true
# - redirect URLs include the exact callback the app uses
# (e.g., https://myapp.com/auth/callback — protocol + host + path must match)
# 3. If config looks right, check insforge.logs for the OAuth error
npx @insforge/cli logs insforge.logs --limit 50Frequently paired with
- logs — metadata says "configured" but logs say "actually broken"; pair to distinguish config drift vs runtime failure
- policies — metadata confirms the table; policies show the RLS gating it
- advisor — security/health issues often name a configured object (bucket, secret, function) for inspection
Metrics
EC2 instance time-series telemetry: CPU, memory, disk, network. The primary primitive for confirming system-wide resource pressure vs an isolated request issue.
Command
npx @insforge/cli diagnose metrics [--range 1h|6h|24h|7d] [--metrics <list>]Default range: 1h.
What you see
| Metric family | Indicates |
|---|---|
| CPU | Compute saturation (sustained >80% = trouble; spike & recover = normal) |
| Memory | Memory pressure (rising over time → leak; near limit + OOM kills → resize) |
| Disk | Storage fill rate, IO saturation (read/write throughput, queue depth) |
| Network | Inbound/outbound bandwidth, packet rate (sudden spike = traffic surge or attack) |
Range selection
| Symptom | Range | Why |
|---|---|---|
| Active incident ("everything is slow right now") | 1h | High-resolution to catch the spike |
| "It was slow ~6 hours ago, what happened?" | 6h | Cover the window with reasonable resolution |
| "Has performance degraded this week?" | 24h or 7d | Trend analysis, not point-in-time |
| Pre-launch baseline | 7d | Establish normal range before traffic |
How to read
1. Start from baseline: what does the normal range look like for this metric? Always look at the trend, not a single point. 2. Correlate to events: spike at a specific timestamp → cross-reference logs for what was happening then. 3. Distinguish saturation vs spike:
- Sustained high = saturation → scale up or fix the load source
- Brief spike + recovery = normal burst → not actionable on its own
Boundaries
- Instance-level only. Metrics show the EC2 box's resource use, not per-request latency or per-query cost. For request-specific perf, combine with logs (
postgres.logsfor slow queries) and db-health. - Doesn't explain causes. Metrics show symptoms (CPU high), not causes (which query, which function). Pair with logs or db-health for root cause.
- Edge function execution is separate. Functions run in their own runtime; their resource use isn't in EC2 metrics.
Example
User reports: "API has been slow for the last 2 hours."
# 1. Check resource pressure over the right window
npx @insforge/cli diagnose metrics --range 6h
# 2. If CPU/memory spiked at a timestamp, line it up with errors
npx @insforge/cli diagnose logs --limit 200
# 3. If DB is the bottleneck (Postgres-heavy CPU patterns)
npx @insforge/cli diagnose dbFrequently paired with
- db-health — DB is the most common bottleneck behind CPU/memory pressure
- logs — correlate metric spikes to log events at the same timestamp
- advisor —
--severity criticalmay already flag the underlying cause (e.g., missing index)
Policies
Active RLS (Row-Level Security) rules pulled from Postgres's pg_policies system view. The primary primitive for what RLS is currently allowing or denying — distinct from "what config we meant to deploy" (that lives in metadata / migration history).
Command
npx @insforge/cli db policiesReturns every policy: table, schema, policy name, command (SELECT / INSERT / UPDATE / DELETE / ALL), target role, USING expression, WITH CHECK expression.
Only specific InsForge-managed tables allow developer RLS changes. Check the relevant module skill or CLI reference before writing policy SQL for a managed table. If that table is listed as allowing RLS changes, normal RLS operations are allowed and should go in migrations.
Policy anatomy
| Field | Meaning |
|---|---|
tablename | Which table the policy applies to |
cmd | Which operation it gates (read/write/all) |
roles | Which DB roles the policy applies to (typically authenticated, anon, public) |
qual (USING) | Filter expression: which existing rows the role can see/modify. Applied to SELECT, UPDATE, DELETE. |
with_check | Validation expression: which new/modified rows are allowed. Applied to INSERT, UPDATE. |
permissive / restrictive | Permissive policies OR together; restrictive AND. Most InsForge projects use permissive. |
How to read
For "why was this request denied?":
1. Identify the table from the request URL (/api/database/records/<table>). 2. List policies for that table — note cmd and roles. 3. Walk the USING / WITH CHECK expressions against the actual request:
- No policy for that role+cmd combo → denied by default. Need to add a policy.
- `USING` evaluates false for this row → row is invisible / not modifiable. Confirm the helper (e.g.,
auth.uid()returns the expected user_id). - `WITH CHECK` evaluates false on insert → the new row's columns violate the policy. The insert payload is wrong, or the policy is too strict.
Common RLS bug shapes
| Symptom | Likely cause |
|---|---|
| All authenticated users see all rows (no isolation) | Policy is USING (true) — too permissive; restrict by user_id column |
| Authenticated user gets empty result on own data | Wrong helper function (auth.uid() returns UUID; if user_id column is TEXT from third-party auth, use requesting_user_id() instead) |
| Insert fails for owner with "new row violates RLS policy" | Missing WITH CHECK matching the USING, or WITH CHECK references columns not in payload |
| Third-party auth (Clerk/Auth0/etc.) users get blanket deny | Wrong helper (auth.uid() expects InsForge-issued JWT; third-party providers need requesting_user_id() with the right claim extraction) |
| Anonymous user can read sensitive table | RLS not enabled on the table (forgot ALTER TABLE ... ENABLE ROW LEVEL SECURITY), or a policy applies to public / anon role without filter, or the connection is using a role with BYPASSRLS |
Boundaries
- Lists active policies, doesn't simulate. Doesn't tell you "this specific request would be allowed" — combine with logs (
postgREST.logs) to see the actual denial event. - Doesn't include the helper function bodies.
auth.uid()/requesting_user_id()are SQL functions; inspect viadb queryif you need to verify they return what you expect. - Only listed managed tables allow RLS changes. Check the relevant module skill or CLI reference before changing RLS on a managed table. If the table is listed, put normal RLS operations in migrations; keep normal schema changes in
public.
Example
User reports: "logged-in user gets 403 trying to GET /api/database/records/posts".
# 1. See the denial event
npx @insforge/cli logs postgREST.logs --limit 50
# 2. List policies on the posts table
npx @insforge/cli db policies
# 3. If the project uses third-party auth, verify the helper
npx @insforge/cli db query "SELECT requesting_user_id()"
# 4. Confirm the user's JWT contains the expected claim (auth config in metadata)
npx @insforge/cli metadata --jsonFrequently paired with
- logs —
postgREST.logsshows the actual RLS denial events; pair with policies to identify which rule fired - metadata — auth config determines which claim feeds
auth.uid()/requesting_user_id() - advisor — security category often flags missing/overly-permissive RLS policies
Related skills
Forks & variants (1)
Insforge Debug has 1 known copy in the catalog totaling 267 installs. They canonicalize to this original listing.
- insforge - 267 installs
How it compares
Use insforge-debug for InsForge-specific RLS, edge, and OAuth signals; use generic backend debug skills for non-InsForge Node or Postgres apps.
FAQ
What does insforge-debug do?
>-
When should I use insforge-debug?
>-
Is insforge-debug safe to install?
Review the Security Audits panel on this page before installing in production.