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 falseView on GitHub (pinned to 988cbb0330)
Solutions
- Check the asynq broker/Redis connectivity (redis-cli ping from the app host)
- Verify the queue name matches a queue a server is consuming
- Inspect the wrapped error (errors.Unwrap / %w chain) for the underlying asynq cause
- 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
- Health-check Redis/asynq before accepting uploads
- Pin queue names in config shared by producer and consumer
- Alert on documents stuck in failed status
- Set sensible asynq retry/dead-letter options
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
- task %s in queue %s cannot run now
- task %s in queue %s cannot be deleted
- WEKNORA_REDIS_NAMESPACE must not contain braces
- WEKNORA_REDIS_NAMESPACE must not contain control characters
- failed to get FAQ import progress from Redis: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/273d298fb5e70811.
Report an issue: GitHub.