chatboxai/chatbox · error · Error

The image request changed after approval. Ask the user to re

Error message

The image request changed after approval. Ask the user to review it again.

What it means

Plain Error (not a usage error) thrown when an approved image-generation request exists but one of its fields (prompt, count, aspectRatio, style, provider when specified, modelId when specified) differs from the current request. The approval is bound to an exact signature; changing any signed field invalidates it and forces re-approval to prevent billing the user for something they did not see.

Source

Thrown at src/renderer/packages/chatbox-cli/images.ts:184

  const requestedAspectRatio = stringFlag(context.parsed, 'aspect-ratio')
  const requestedStyle = stringFlag(context.parsed, 'style')
  if (requestedStyle && requestedStyle !== 'vivid' && requestedStyle !== 'natural') {
    throw new ChatboxCliUsageError('--style must be vivid or natural.')
  }
  const parsedStyle: 'vivid' | 'natural' | undefined =
    requestedStyle === 'vivid' || requestedStyle === 'natural' ? requestedStyle : undefined
  const approvedRequest =
    context.approved && context.approvalDetails?.type === 'image_generation' ? context.approvalDetails : undefined
  if (
    approvedRequest &&
    (approvedRequest.prompt !== requestedPrompt ||
      approvedRequest.count !== requestedCount ||
      approvedRequest.aspectRatio !== requestedAspectRatio ||
      approvedRequest.style !== parsedStyle ||
      (requestedProvider !== undefined && approvedRequest.provider !== requestedProvider) ||
      (requestedModelId !== undefined && approvedRequest.modelId !== requestedModelId))
  ) {
    throw new Error('The image request changed after approval. Ask the user to review it again.')
  }

  const prompt = approvedRequest?.prompt ?? requestedPrompt
  const count = approvedRequest?.count ?? requestedCount
  const aspectRatio = approvedRequest?.aspectRatio ?? requestedAspectRatio
  const dalleStyle = approvedRequest?.style ?? parsedStyle

  const cacheKey = `${sessionId}:${toolCallId}`
  const persistedExecutionKey = imageExecutionStorageKey(sessionId, toolCallId)
  const existing = executionCache.get(cacheKey)
  const persistedExecutionValue = existing ? null : await storage.getItem<unknown>(persistedExecutionKey, null)
  if (persistedExecutionValue !== null && !isPersistedImageExecution(persistedExecutionValue)) {
    throw new Error(`Stored image execution metadata is invalid for tool call ${cacheKey}.`)
  }
  const boundSignature = existing?.signature ?? persistedExecutionValue?.signature
  const boundRequest = boundSignature ? parseImageExecutionSignature(boundSignature) : undefined
  if (boundSignature && !boundRequest) {
    throw new Error(`Stored image execution signature is invalid for tool call ${cacheKey}.`)

View on GitHub (pinned to 81571269ad)

Solutions

  1. Keep the request fields identical between approval and execution; do not mutate them after the user approves.
  2. If parameters must change, start a fresh request and request approval again rather than reusing the tool-call id.
  3. Treat this error as terminal for the current tool-call and re-prompt the user for fresh approval.

Example fix

// before: agent tweaks prompt after approval
approvedDetails.prompt = newPrompt
await generateImage(ctx)

// after: start a new approved request instead
await requestAppActionApproval(newToolCallId, 'image.generate', ...)
// then dispatch with the new tool-call id and identical fields
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the executed request matches the approved signature exactly.
function matchesApproval(req: ImageRequest, apv: ImageRequest): boolean {
  return (
    req.prompt === apv.prompt &&
    req.count === apv.count &&
    req.aspectRatio === apv.aspectRatio &&
    req.style === apv.style &&
    (req.provider === undefined || req.provider === apv.provider) &&
    (req.modelId === undefined || req.modelId === apv.modelId)
  )
}
if (approved && !matchesApproval(currentRequest, approvedRequest)) {
  // start a fresh approval flow instead of reusing the tool-call id
}

Try / catch

try {
  await generateImage(ctx)
} catch (error) {
  if (error instanceof Error && error.message.includes('changed after approval')) {
    // terminal: re-request approval with the new parameters; do not retry as-is
  } else throw error
}

Prevention

When it happens

Trigger: User approved a request, then the prompt/count/aspect-ratio/style/provider/model changed before execution; or an LLM reused the approved tool-call id with tweaked arguments.

Common situations: An agent editing the prompt after the approval card, a retry that altered parameters, or stale approval details reused across turns.

Related errors


AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12). Data as JSON: /api/errors/c76b6d255374c534. Report an issue: GitHub.