siyuan-note/siyuan · warning

image generation was cancelled

Error message

image generation was cancelled

What it means

Returned by GenerateImage when Generate returned no error but ctx.Err() is non-nil afterwards — the caller's context was cancelled or expired while the provider was processing. Because the request already reached the provider (and may still produce a charge/result), it is wrapped with markImageExecutionUnknown and must not be retried automatically.

Source

Thrown at kernel/model/assets.go:440

	if prompt == "" {
		return GenerateImageResult{}, errors.New("prompt is required for image generation")
	}
	size := multimodalValueOrDefault(request.Size, Conf.AI.ImageGeneration.Size)
	quality := multimodalValueOrDefault(request.Quality, Conf.AI.ImageGeneration.Quality)
	outputFormat := strings.ToLower(multimodalValueOrDefault(request.OutputFormat, Conf.AI.ImageGeneration.OutputFormat))
	if outputFormat != "png" && outputFormat != "jpeg" && outputFormat != "webp" {
		return GenerateImageResult{}, errors.New("unsupported image output format")
	}
	generated, err := util.NewOpenAIImageAdapter(
		provider.APIKey, provider.BaseURL, generationModel.Name, Conf.AI.ImageGeneration.RequestTimeout,
	).Generate(ctx, util.GenerateImageRequest{
		Prompt: prompt, Size: size, Quality: quality, OutputFormat: outputFormat,
	})
	if err != nil {
		return GenerateImageResult{}, markImageExecutionUnknown(fmt.Errorf("generate image failed: %w", err))
	}
	if ctx.Err() != nil {
		return GenerateImageResult{}, markImageExecutionUnknown(errors.New("image generation was cancelled"))
	}
	return GenerateImageResult{
		Data: generated.Data, MIMEType: generated.MIMEType, Extension: generated.Extension, RevisedPrompt: generated.RevisedPrompt,
	}, nil
}

// GenerateDocumentImage 使用通用图片生成能力创建文档资源。
func GenerateDocumentImage(ctx context.Context, request GenerateDocumentImageRequest) (GenerateDocumentImageResult, error) {
	bt, err := resolveMultimodalDocument(request.DocumentID)
	if err != nil {
		return GenerateDocumentImageResult{}, err
	}
	generated, err := GenerateImage(ctx, GenerateImageRequest{
		Prompt: request.Prompt, Size: request.Size, Quality: request.Quality, OutputFormat: request.OutputFormat,
	})
	if err != nil {
		return GenerateDocumentImageResult{}, err
	}

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Treat as terminal for this attempt: do not retry on the same context (it is already cancelled).
  2. If the user wants to try again, start a fresh context with a longer timeout and confirm with the user first.
  3. Raise Conf.AI.ImageGeneration.RequestTimeout if cancellations are timeout-driven, not user-driven.

Example fix

// before
res, err := model.GenerateImage(ctx, req)
if err != nil { res, err = model.GenerateImage(ctx, req) } // ctx already dead — loops forever

// after
res, err := model.GenerateImage(ctx, req)
if err != nil && model.IsImageExecutionUnknown(err) {
    if ctx.Err() != nil {
        return fmt.Errorf("cancelled by caller (%w); not retrying", ctx.Err())
    }
    return err
}
Defensive patterns

Strategy: try-catch

Type guard

func isCancelledGeneration(err error) bool {
    return model.IsImageExecutionUnknown(err)
}

Try / catch

res, err := model.GenerateImage(ctx, req)
if err != nil && model.IsImageExecutionUnknown(err) && ctx.Err() != nil {
    // caller's context died — do not retry on the same (dead) context
    return fmt.Errorf("generation cancelled: %w", ctx.Err())
}

Prevention

When it happens

Trigger: The user cancelled the operation; a parent context deadline (RequestTimeout or higher-level timeout) fired mid-call; the kernel is shutting down and cancelled the ctx.

Common situations: User clicked cancel on a long generation; the client closed the WebSocket/HTTP connection so the kernel cancelled the ctx; an aggressive outer timeout wraps the call.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/0b8e09338acdbd74. Report an issue: GitHub.