Tencent/WeKnora · error

failed to update chunk status: %w

Error message

failed to update chunk status: %w

What it means

After successful indexing, CreateFAQEntry flips chunk.Status to ChunkStatusIndexed and persists via chunkService.UpdateChunk; failure is wrapped with this message. The entry is already created and indexed, but its status marker remains Stored, so it may not appear in listings or may be re-indexed. This is a DB update failure, not an indexing problem.

Source

Thrown at internal/application/service/knowledge_faq.go:249

	// 索引chunk:交互式创建给索引步骤设硬上限,避免 embedding 抖动把请求拖长
	indexCtx, cancelIndex := context.WithTimeout(ctx, faqCreateIndexBudget)
	indexErr := s.indexFAQChunks(indexCtx, kb, faqKnowledge, []*types.Chunk{chunk}, embeddingModel, true, false)
	cancelIndex()
	if indexErr != nil {
		// 如果索引失败,删除已创建的chunk。回滚失败会留下一条 stored 状态的
		// 残留:它不出现在列表里,却会被重复校验命中,因此必须告警而非静默。
		if delErr := s.chunkService.DeleteChunk(ctx, chunk.ID); delErr != nil {
			logger.Errorf(ctx,
				"CreateFAQEntry: rollback failed, chunk %s left in stored state: %v", chunk.ID, delErr)
		}
		return nil, fmt.Errorf("failed to index chunk: %w", indexErr)
	}

	// 更新chunk状态为已索引
	chunk.Status = int(types.ChunkStatusIndexed)
	if err := s.chunkService.UpdateChunk(ctx, chunk); err != nil {
		return nil, fmt.Errorf("failed to update chunk status: %w", err)
	}

	// Build tag seq_id map for conversion
	tagSeqIDMap := make(map[string]int64)
	if chunk.TagID != "" {
		tag, tagErr := s.tagRepo.GetByID(ctx, tenantID, chunk.TagID)
		if tagErr == nil && tag != nil {
			tagSeqIDMap[tag.ID] = tag.SeqID
		}
	}

	// 转换为FAQEntry返回
	entry, err := s.chunkToFAQEntry(chunk, kb, tagSeqIDMap)
	if err != nil {
		return nil, err
	}

	// 查询TagName

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Check the wrapped DB error and retry the operation; if a duplicate question blocks re-creation, delete or manually flip the stale chunk's status to indexed.
  2. Repair the inconsistent chunk directly: UPDATE the chunk status to indexed (or delete it) so listings and duplicate checks behave correctly.
  3. Increase request timeouts to avoid context cancellation before the final status write.
  4. Check DB lock contention/deadlocks on the chunk table under concurrent FAQ creation.

Example fix

// after hitting this error, repair the stuck chunk
chunk, _ := chunkRepo.GetByID(ctx, chunkID)
chunk.Status = int(types.ChunkStatusIndexed)
chunkRepo.Update(ctx, chunk) // or delete if the entry should not exist
Defensive patterns

Strategy: try-catch

Validate before calling

if err := db.PingContext(ctx); err != nil {
	return fmt.Errorf("database unhealthy; FAQ create may end in inconsistent status: %w", err)
}

Try / catch

entry, err := svc.CreateFAQEntry(ctx, kbID, payload)
if err != nil && strings.Contains(err.Error(), "failed to update chunk status") {
	// entry is indexed but status is stale; reconcile by listing/re-fetching
	// or delete the chunk if the entry should not exist
	log.Warn("FAQ created but status update failed; reconcile chunk status", "kb", kbID)
}

Prevention

When it happens

Trigger: Calling CreateFAQEntry when the post-index UpdateChunk write fails: DB connection loss, deadlock/lock wait timeout on the chunk row, request context cancelled between index completion and the update, or optimistic-concurrency conflict if the row changed concurrently.

Common situations: Transient DB blip right after embedding finished; long requests whose context expires during the final write; heavy write contention on the chunk table; connection pool exhaustion.

Related errors


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