Tencent/WeKnora · error

schedule attachment parsing: %w

Error message

schedule attachment parsing: %w

What it means

Create persists the temporary document and then enqueues an asynq task for parsing; if enqueueing fails, the document is marked failed and the enqueue error is wrapped with this prefix. The root cause is the asynq broker (usually Redis) being unreachable or rejecting the task.

Source

Thrown at internal/application/service/temporary_document.go:207

		return nil, fmt.Errorf("create attachment record: %w", err)
	}
	if s.resourceCatalog != nil {
		if err := s.resourceCatalog.Bind(ctx, resourceRef, types.ResourceOwnerTemporaryDocument, document.ID, types.ResourceRelationSourceFile); err != nil {
			_ = s.repo.DeleteScoped(ctx, tenantID, sessionID, document.ID)
			_ = s.fileService.DeleteFile(ctx, resourceRef)
			return nil, fmt.Errorf("bind attachment resource: %w", err)
		}
	}
	payload, _ := json.Marshal(types.TemporaryDocumentTaskPayload{TenantID: tenantID, DocumentID: document.ID})
	queue, _ := types.QueueForTaskType(types.TypeTemporaryDocumentProcess)
	if _, err := s.taskEnqueuer.Enqueue(
		asynq.NewTask(types.TypeTemporaryDocumentProcess, payload),
		asynq.Queue(queue), asynq.MaxRetry(2), asynq.Timeout(10*time.Minute),
	); err != nil {
		_ = s.repo.MarkFailed(ctx, tenantID, document.ID, "failed to schedule document parsing")
		document.Status = types.TemporaryDocumentStatusFailed
		document.ErrorMessage = "failed to schedule document parsing"
		return document, fmt.Errorf("schedule attachment parsing: %w", err)
	}
	return document, nil
}

func (s *temporaryDocumentService) supportsExtension(ctx context.Context, tenantID uint64, ext string) bool {
	if _, ok := temporaryDocumentExtensions[ext]; ok {
		return true
	}
	if s.documentReader == nil {
		return false
	}
	var overrides map[string]string
	if tenant, err := s.tenantService.GetTenantByID(ctx, tenantID); err == nil && tenant != nil {
		overrides = tenant.ParserEngineConfig.ToOverridesMap()
	}
	engines, err := s.documentReader.ListEngines(ctx, overrides)
	if err != nil {
		return false

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Check the asynq broker/Redis connectivity (redis-cli ping from the app host)
  2. Verify the queue name matches a queue a server is consuming
  3. Inspect the wrapped error (errors.Unwrap / %w chain) for the underlying asynq cause
  4. Implement a retry or fallback synchronous path for scheduling, and alert on repeated MarkFailed records

Example fix

// before
client.Enqueue(task, asynq.Queue("tempdoc"))
// after
if err := client.Enqueue(task, asynq.Queue(queue)); err != nil {
    logger.Error("enqueue failed", "err", err, "queue", queue)
    return fmt.Errorf("schedule attachment parsing: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if err := broker.Ping(); err != nil { return fmt.Errorf("task broker unavailable: %w", err) }

Try / catch

doc, err := svc.Create(ctx, req)
var wrapped *fmt.wrapError
if err != nil && errors.As(err, &wrapped) && strings.HasPrefix(err.Error(), "schedule attachment parsing:") {
    // broker failure: surface 503 and/or retry Create
}

Prevention

When it happens

Trigger: Redis down or misconfigured for asynq; invalid queue name; payload marshal failure; task option conflicts (queue/timeout) rejected by the broker.

Common situations: Redis connection limits exhausted in prod; wrong REDIS_ADDR env; queue name typo after a rename; network partition between app and broker.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/273d298fb5e70811. Report an issue: GitHub.