chatboxai/chatbox · warning · Error

Embedding batch failed: expected ${batchTexts.length}, got $

Error message

Embedding batch failed: expected ${batchTexts.length}, got ${embeddingResult.embeddings?.length || 0}

What it means

Thrown at the top of Gemini.paint() (built-in Google Gemini provider) when `isGeminiImageModel(this.options.model.modelId)` is false. Same guard as CustomGemini.paint(): the model id must contain both 'gemini' and 'image'. Fires before any network call, so it is a capability check — paint() was invoked on a text-only Gemini model.

Source

Thrown at src/main/knowledge-base/file-loaders.ts:202

      }

      const batchChunks = remainingChunks.slice(i, i + BATCH_SIZE)
      const batchTexts = batchChunks.map((chunk: any) => `filename: ${fileMeta.filename}\nchunk:\n${chunk.text}`)

      const batchNumber = Math.floor(i / BATCH_SIZE) + 1
      const totalBatches = Math.ceil(remainingChunks.length / BATCH_SIZE)
      log.debug(`[FILE] Processing batch ${batchNumber}/${totalBatches}, chunks: ${batchTexts.length}`)

      // Generate embeddings for this batch
      const embeddingResult = await embedMany({
        model: embeddingInstance,
        values: batchTexts,
        // Embeddings are billable; network-error retries could double-charge.
        maxRetries: 0,
      })

      if (!embeddingResult.embeddings || embeddingResult.embeddings.length !== batchTexts.length) {
        throw new Error(
          `Embedding batch failed: expected ${batchTexts.length}, got ${embeddingResult.embeddings?.length || 0}`
        )
      }

      // Store vectors for this batch
      log.debug(`[FILE] Storing batch ${batchNumber}/${totalBatches} to vector store`)
      await vectorStore.upsert({
        indexName,
        vectors: embeddingResult.embeddings,
        metadata: batchChunks.map((chunk: any, chunkIndex: number) => ({
          text: chunk.text,
          fileId: fileMeta.fileId,
          filename: fileMeta.filename,
          mimeType: fileMeta.mimeType,
          chunkIndex: currentChunkCount + i + chunkIndex, // Use absolute chunk index
        })),
      })

View on GitHub (pinned to 81571269ad)

Solutions

  1. Gate the image-generation UI on `isGeminiImageModel(modelId)` and disable the paint button for non-matching models.
  2. Switch to a recognised Gemini image model (`gemini-2.0-flash-exp-image-generation`, `gemini-2.5-flash-image-preview`).
  3. Keep image-models.ts in sync if Google ships image models whose id does not match the `gemini`+`image` rule.
  4. If you call paint() programmatically, assert the capability first and surface a typed error to the caller rather than letting ApiError propagate.

Example fix

// before
const images = await gemini.paint({ prompt, num: 1 })  // throws on text models

// after
if (!isGeminiImageModel(gemini.options.model.modelId)) {
  throw new Error(`Model ${gemini.options.model.modelId} cannot generate images`)
}
const images = await gemini.paint({ prompt, num: 1 })
Defensive patterns

Strategy: validation

Validate before calling

function canPaint(modelId: string): boolean {
  return modelId.includes('gemini') && modelId.includes('image')
}
if (!canPaint(session.modelId)) disablePaintUI()

Type guard

import { isGeminiImageModel } from '../image-models'
function assertImageCapable(modelId: string): void {
  if (!isGeminiImageModel(modelId)) throw new Error(`Model ${modelId} cannot generate images`)
}

Try / catch

try { await gemini.paint({ prompt, num: 1 }) }
catch (e) {
  if (e instanceof ApiError && e.message.includes('does not support image generation')) {
    showWarning('Select a Gemini image model to generate images')
    return []
  }
  throw e
}

Prevention

When it happens

Trigger: User opens image generation while a text Gemini model (e.g. `gemini-2.5-pro`, `gemini-2.0-flash`) is the active session model; a stored session restored a non-image model and the paint action is invoked automatically; the model nickname differs from its id and the UI dispatched paint() based on display name rather than id-based capability check.

Common situations: Newly added Gemini text model selected by default after a refresh; user expects all Gemini models to generate images; image model id changed in a Google API revision and the new id lacks the 'image' substring; the UI does not pre-check capability before showing the paint affordance.

Related errors


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