{"record":{"id":"9b1916a829603dbc","repo":"chatboxai/chatbox","slug":"another-image-is-being-generated-please-wait","errorCode":null,"errorMessage":"Another image is being generated. Please wait.","messagePattern":"Another image is being generated\\. Please wait\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/renderer/stores/imageGenerationActions.ts","lineNumber":131,"sourceCode":"\n/**\n * Starts image generation without waiting for the provider task to finish.\n * Callers that need background-task notifications can observe `completion`;\n * existing UI callers can keep using `createAndGenerate` and only consume the id.\n */\nexport async function startImageGeneration(\n  params: GenerateImageParams,\n  options: StartImageGenerationOptions = {}\n): Promise<ImageGenerationHandle> {\n  const store = imageGenerationStore.getState()\n\n  // Normalize: 'auto' means no aspect ratio constraint\n  if (params.aspectRatio === 'auto') {\n    params = { ...params, aspectRatio: undefined }\n  }\n\n  if (store.currentGeneratingId !== null) {\n    throw new Error('Another image is being generated. Please wait.')\n  }\n\n  const record = await createRecord({\n    prompt: params.prompt,\n    referenceImages: params.referenceImages,\n    model: params.model,\n    dalleStyle: params.dalleStyle,\n    imageGenerateNum: params.imageGenerateNum,\n    parentIds: params.parentIds,\n    aspectRatio: params.aspectRatio,\n    source: params.source,\n  })\n\n  try {\n    await options.onRecordCreated?.(record)\n  } catch (error) {\n    await updateRecord(record.id, getErrorRecordUpdate(error))\n    throw error","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/renderer/stores/imageGenerationActions.ts#L113-L149","documentation":"Single-flight guard at the top of startImageGeneration. The store tracks currentGeneratingId; if it is non-null another generation owns the slot and the call is rejected before creating a record. This prevents two concurrent generations from racing on the shared currentAbortController and store state.","triggerScenarios":"startImageGeneration invoked while imageGenerationStore.getState().currentGeneratingId !== null. Causes: double-click on the generate button, two UI surfaces triggering at once, or a previous generation that failed to clear currentGeneratingId in its finally block.","commonSituations":"User double-taps generate, a previous generation crashed before reaching the finally that resets currentGeneratingId (leaked lock), or retry/resume invoked concurrently with an in-flight start.","solutions":["Disable the generate button while currentGeneratingId is non-null (subscribe to the store in the UI).","Ensure every start path reaches its finally that calls setCurrentGeneratingId(null).","Return a typed 'busy' result instead of throwing so the UI can ignore it without error UX.","Add a timeout/watchdog that clears a stuck currentGeneratingId if no progress for N seconds."],"exampleFix":"// before\nif (store.currentGeneratingId !== null) {\n  throw new Error('Another image is being generated. Please wait.')\n}\n// after\nif (store.currentGeneratingId !== null) {\n  return { status: 'busy' } as ImageGenerationHandle\n}","handlingStrategy":"validation","validationCode":"const busy = imageGenerationStore.getState().currentGeneratingId !== null\nif (busy) return // ignore secondary trigger","typeGuard":"function isSlotFree(s: { currentGeneratingId: string | null }): boolean {\n  return s.currentGeneratingId === null\n}","tryCatchPattern":null,"preventionTips":["Disable the generate button while currentGeneratingId is non-null.","Ensure every start path reaches the finally that clears currentGeneratingId.","Return a non-throwing 'busy' result for an expected precondition."],"tags":["image-generation","concurrency","single-flight","state"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}