pbakaus/impeccable · error · Error

${parts.join('\n')}

Error message

${parts.join('\n')}

What it means

Thrown by postReply() in live-poll.mjs after a POST to the /poll endpoint returns a non-OK HTTP status. The message is dynamically assembled by joining server-supplied fields: body.error (or res.statusText as fallback), body.reason, body.hint, a formatted list of per-file failures (body.failures with file/line/message), and body._instructions — all newline-separated. So the visible text is the server's structured rejection rendered for the console.

Source

Thrown at skill/scripts/live-poll.mjs:126

}

export function requiresAgentReply(event) {
  return EVENT_TYPES_NEEDING_AGENT_REPLY.has(event?.type);
}

export async function postReply(base, token, reply) {
  const res = await fetch(`${base}/poll`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(buildPollReplyPayload(token, reply)),
  });
  if (!res.ok) {
    const body = await res.json().catch(() => ({}));
    const failureLines = Array.isArray(body.failures)
      ? body.failures.map((f) => `  ${f.file}${f.line != null ? `:${f.line}` : ''} ${f.message}`).join('\n')
      : null;
    const parts = [body.error || res.statusText, body.reason, body.hint, failureLines, body._instructions].filter(Boolean);
    throw new Error(parts.join('\n'));
  }
}

export async function fetchServerStatus(base, token) {
  const res = await fetch(`${base}/status?token=${token}`);
  if (res.status === 401) {
    const err = new Error('Authentication failed. The server token may have changed.');
    err.code = 'AUTH_FAILED';
    throw err;
  }
  if (!res.ok) {
    throw new Error(`Status failed: ${res.status} ${res.statusText}`);
  }
  return res.json();
}

export function isEventPending(status, eventId) {
  return (status.pendingEvents || []).some((entry) => entry.id === eventId);

View on GitHub (pinned to d14711ae3d)

Solutions

  1. Read the joined message: the 'failures' lines pin point each file:line problem — fix the named locations and resend.
  2. If the message includes a hint or _instructions block, follow it before retrying.
  3. If it smells like an auth/stale-session issue, refresh status via fetchServerStatus to confirm the token is still valid before re-replying.
  4. Retry only after correcting the underlying payload; an identical retry will keep failing.
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the reply payload shape before posting.
function isValidReply(r) {
  return r && typeof r.eventId !== 'undefined' && (typeof r.status === 'string' && !r.status.startsWith('--'));
}
if (!isValidReply(reply)) throw new Error('reply shape invalid — not posting');

Try / catch

try {
  await postReply(base, token, reply);
} catch (err) {
  // The message is newline-joined server fields; surface it whole.
  if (/Authentication failed/.test(err.message) || err.code === 'AUTH_FAILED') throw err;
  console.error('Reply rejected by server:\n' + err.message);
  // Do NOT retry identical payload — fix the cited file:line failures first.
}

Prevention

When it happens

Trigger: postReply(base, token, reply) is called (e.g. by the live agent replying to a surfaced event). The server responds with a non-2xx status and a JSON body containing error/reason/hint/failures. Common: 4xx for a malformed reply payload, a reply referencing an already-acked or expired event, or an injection that failed server-side validation (failures[] populated with file:line message).

Common situations: The agent replied with a patch/injection that the server rejected (bad anchor, file not found, syntax error at a line); token mismatch surfaced as a 4xx instead of a clean 401; event lease expired and the server no longer recognizes the event id; server was upgraded and the reply schema changed.

Related errors


AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13). Data as JSON: /api/errors/4484263a80d07583. Report an issue: GitHub.