linshenkx/prompt-optimizer · error · ImageError

TEXT2IMAGE_INPUT_IMAGE_NOT_ALLOWED

TEXT2IMAGE_INPUT_IMAGE_NOT_ALLOWED

Error message

TEXT2IMAGE_INPUT_IMAGE_NOT_ALLOWED

What it means

An explicit text-to-image request must not carry input images. validateText2ImageRequest inspects even untyped `inputImage` fields (cast through any) and throws TEXT2IMAGE_INPUT_IMAGE_NOT_ALLOWED when a single input image is present on a text2image call.

Source

Thrown at packages/core/src/services/image/service.ts:81

    // 兼容入口:仍按是否携带 inputImage 判断模式。
    // 注意:这是 legacy 行为;推荐调用方使用显式的 validateText2ImageRequest/validateImage2ImageRequest。
    if (request.inputImage) {
      const image2image: Image2ImageRequest = { ...request, inputImage: request.inputImage }
      await this.validateImage2ImageRequest(image2image)
      return
    }

    const { inputImage: _inputImage, ...rest } = request
    const text2image: Text2ImageRequest = rest
    await this.validateText2ImageRequest(text2image)
  }

  async validateText2ImageRequest(request: Text2ImageRequest): Promise<void> {
    // 显式文生图:不允许携带 inputImage(即使调用方用 any 绕过类型)
    const unsafeInputImage = (request as unknown as { inputImage?: unknown }).inputImage
    const unsafeInputImages = (request as unknown as { inputImages?: unknown }).inputImages
    if (unsafeInputImage !== undefined && unsafeInputImage !== null) {
      throw new ImageError(IMAGE_ERROR_CODES.TEXT2IMAGE_INPUT_IMAGE_NOT_ALLOWED)
    }
    if (Array.isArray(unsafeInputImages) && unsafeInputImages.length > 0) {
      throw new ImageError(IMAGE_ERROR_CODES.TEXT2IMAGE_INPUT_IMAGE_NOT_ALLOWED)
    }

    await this.validateBaseRequest(request)

    const config = await this.imageModelManager.getConfig(request.configId)
    if (!config) {
      throw new ImageError(IMAGE_ERROR_CODES.CONFIG_NOT_FOUND, undefined, { configId: request.configId })
    }

    // 能力校验:优先使用 config.model(动态/自定义模型),静态列表作为兜底
    const configModel = config.model
    const staticModels = this.registry.getStaticModels(config.providerId)
    const staticModel = staticModels.find(m => m.id === config.modelId)
    const capabilities = configModel?.capabilities ?? staticModel?.capabilities
    const modelName = configModel?.name ?? staticModel?.name ?? config.modelId

View on GitHub (pinned to 3e677b1d9f)

Solutions

  1. Delete inputImage before sending: const { inputImage, ...rest } = request; generateText2Image(rest)
  2. Fix the UI to reset input image state when switching to text2image mode
  3. Use generateImage2Image when you actually want image conditioning

Example fix

// before
await service.generateText2Image({ ...formState } as any) // formState still has inputImage

// after
const { inputImage, inputImages, ...t2i } = formState
await service.generateText2Image(t2i)
Defensive patterns

Strategy: validation

Validate before calling

function toStrictT2I<T extends Record<string, any>>(req: T): Omit<T, 'inputImage' | 'inputImages'> {
  const { inputImage, inputImages, ...rest } = req
  return rest
}
// usage: await service.generateText2Image(toStrictT2I(formState) as Text2ImageRequest)

Type guard

function isPureText2ImageRequest(r: unknown): boolean {
  const o = r as any
  return (o?.inputImage === undefined || o?.inputImage === null) &&
    !(Array.isArray(o?.inputImages) && o.inputImages.length > 0)
}

Try / catch

try {
  await service.generateText2Image(req as Text2ImageRequest)
} catch (e) {
  if (e instanceof ImageError && e.code === IMAGE_ERROR_CODES.TEXT2IMAGE_INPUT_IMAGE_NOT_ALLOWED) {
    const { inputImage, inputImages, ...clean } = req as any
    return service.generateText2Image(clean)
  }
  throw e
}

Prevention

When it happens

Trigger: Calling generateText2Image or validateRequest with a request object that includes a non-null `inputImage` property — typically because a form/UI reused an image2image request object, or a caller added inputImage via any-typed spread.

Common situations: UI mode toggle between img2img and t2i not stripping inputImage from the shared request state; deserializing a saved request of the wrong type; API consumers sending a 'kitchen sink' payload.

Related errors


AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27). Data as JSON: /api/errors/c3882ce61bc3c14d. Report an issue: GitHub.