garrytan/gstack · error · Error

Save blocked: ${filterResult.message} Cause: skill body trip

Error message

Save blocked: ${filterResult.message}
Cause: skill body trips L1-L3 content filters (likely contains URL blocklist match or ARIA injection patterns).
Action: review the body for suspicious instruction-like content; rewrite and retry.

What it means

Error "Save blocked: ${filterResult.message} Cause: skill body trips L1-L3 content filters (likely contains URL blocklist match or ARIA injection patterns). Action: review the body for suspicious instruction-like content; rewrite and retry." thrown in garrytan/gstack.

Source

Thrown at browse/src/domain-skill-commands.ts:125

async function handleSave(args: string[], bm: BrowserManager): Promise<string> {
  const page = bm.getPage();
  const host = await deriveHostFromActiveTab(page);
  const body = await readBodyFromArgs(args);
  if (!body || !body.trim()) {
    throw new Error(
      'Save failed: empty body.\n' +
        'Cause: no content provided via --from-file or stdin.\n' +
        'Action: pipe markdown into $B domain-skill save, or pass --from-file <path>.'
    );
  }
  // L1-L3 content filters (datamarking, hidden-element strip, ARIA regex,
  // URL blocklist). The full L4 ML classifier runs at sidebar-agent prompt
  // injection time, not here (CLAUDE.md: classifier can't import in compiled binary).
  const filterResult = runContentFilters(body, page.url(), 'domain-skill-save');
  if (filterResult.blocked) {
    logTelemetry({ event: 'domain_skill_save_blocked', host, reason: filterResult.message });
    throw new Error(
      `Save blocked: ${filterResult.message}\n` +
        'Cause: skill body trips L1-L3 content filters (likely contains URL blocklist match or ARIA injection patterns).\n' +
        'Action: review the body for suspicious instruction-like content; rewrite and retry.'
    );
  }
  // L1-L3 score is binary (passed or not). For the L4 score field we leave 0
  // (meaning "not yet scanned by ML classifier") — sidebar-agent fills this
  // in on first prompt-injection load.
  const slug = getCurrentProjectSlug();
  const row = await writeSkill({
    host,
    body,
    projectSlug: slug,
    source: 'agent',
    classifierScore: 0, // L4 deferred to load-time
  });
  logTelemetry({ event: 'domain_skill_saved', host, scope: row.scope, state: row.state, bytes: body.length });
  return formatSavedOk(row, slug);

View on GitHub (pinned to 94993f7401)

When it happens

Trigger: Thrown at browse/src/domain-skill-commands.ts:125 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12). Data as JSON: /api/errors/47afe62982f52714. Report an issue: GitHub.