siyuan-note/siyuan · warning

image generation was cancelled

Error message

image generation was cancelled

What it means

After the adapter call succeeds, GenerateImage checks ctx.Err(); if the caller's context was cancelled or its deadline expired during generation, the result is discarded and "image generation was cancelled" is returned (also marked as execution-unknown). This prevents committing images whose generation the caller no longer wants.

Solutions

  1. Retry with a fresh, non-cancelled context if the generation is still wanted
  2. Use context.WithTimeout with a generous deadline (at least Conf.AI.ImageGeneration.RequestTimeout plus margin)
  3. If cancellation is intentional (user abort), treat this error as expected and skip reporting it to the user

Example fix

// before
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
// after
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
result, err := model.GenerateImage(ctx, req)
Defensive patterns

Strategy: try-catch

Validate before calling

if ctx.Err() != nil {
    return errors.New("context already cancelled before generation started")
}

Try / catch

res, err := model.GenerateImage(ctx, req)
if err != nil && err.Error() == "image generation was cancelled" {
    if errors.Is(ctx.Err(), context.DeadlineExceeded) {
        // retry with a longer deadline
    }
    // user-initiated cancellation: log and return quietly
}

Prevention

When it happens

Trigger: The caller's context.Context is cancelled (user aborted, request shut down) or its deadline passes while the provider request is in flight or just as it completes.

Common situations: Closing the AI chat panel mid-generation; an HTTP client disconnecting cancels the gin request context; a short parent deadline (e.g. 30s) expiring before a slow provider finishes.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/0b8e09338acdbd74. Report an issue: GitHub.

Appendix: source

Thrown at kernel/model/assets.go:548

	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, ResolveAIProviderHeaders(provider),
	).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 9f775e8a12)