Tencent/WeKnora · info
concurrent wiki task active
Error message
concurrent wiki task active
What it means
ErrWikiIngestConcurrent is a sentinel returned when a wiki ingest batch task starts for a knowledge base that already has an active batch (the in-process liteLocks guard is held). The asynq RetryDelayFunc matches it with errors.Is to apply a short fixed retry delay instead of exponential backoff, so the deferred batch retries promptly. Standard/Redis mode no longer takes an exclusive per-KB lock and never returns this.
Source
Thrown at internal/application/service/wiki_ingest.go:36
"github.com/Tencent/WeKnora/internal/models/chat"
"github.com/Tencent/WeKnora/internal/searchutil"
"github.com/Tencent/WeKnora/internal/tracing/langfuse"
"github.com/Tencent/WeKnora/internal/types"
"github.com/Tencent/WeKnora/internal/types/interfaces"
"github.com/google/uuid"
"github.com/hibiken/asynq"
"github.com/redis/go-redis/v9"
"golang.org/x/sync/singleflight"
)
// ErrWikiIngestConcurrent is returned by the wiki ingest handler in Lite mode
// when another batch is already running for the same KB (the in-process
// liteLocks guard is held). The asynq/sync executor's RetryDelayFunc uses
// errors.Is on this sentinel to apply a short, fixed retry delay instead of
// exponential backoff, so the deferred batch retries promptly once the active
// one releases. Standard (Redis) mode no longer takes an exclusive per-KB
// lock (Phase 3) and never returns this.
var ErrWikiIngestConcurrent = errors.New("concurrent wiki task active")
const (
// maxContentForWiki limits the document content sent to LLM for wiki generation
maxContentForWiki = 32768
// --- Phase 3: concurrent per-KB batches (standard/Redis mode) ---------
//
// Phase 3 removed the exclusive per-KB Redis "batch in progress" lock
// (wiki:active:<kbID>). Standard mode now allows concurrent batches for
// one KB, kept safe by row claiming (claimPendingList) plus per-slug
// reduce locks (withSlugLock). Lite mode still serializes per KB via the
// in-process liteLocks map.
//
// wikiClaimStaleAfter is how long a claimed-but-undrained ingest row
// waits before another worker may re-claim it. It MUST exceed the asynq
// task Timeout for wiki:ingest (60m) so a still-running batch's rows are
// never stolen mid-flight — only genuinely crashed/abandoned claims are
// recovered. This preserves the pre-claim crash behaviour where a deadView on GitHub (pinned to 988cbb0330)
Solutions
- No action needed — the executor retries with wikiIngestRetryDelay until the active batch releases the lock.
- Reduce duplicate triggers by debouncing wiki ingest enqueues per KB.
- If it persists, investigate why the active batch is slow or stuck (LLM timeouts) and check liteLocks cleanup on panic paths.
Defensive patterns
Strategy: retry
Try / catch
// executor RetryDelayFunc
if errors.Is(err, service.ErrWikiIngestConcurrent) {
return wikiIngestRetryDelay // short fixed delay, not backoff
} Prevention
- Debounce wiki ingest enqueues per knowledge base.
- Monitor batch durations so long LLM runs don't stack up deferred retries.
- Don't treat this error as a failure — it is an expected deferral signal.
When it happens
Trigger: Processing a wiki ingest payload for a KB while ProcessWikiIngest (or the batch executor in wiki_ingest_batch.go) finds another batch still running for the same KnowledgeBaseID under liteLocks.
Common situations: Duplicate enqueue of wiki ingest tasks for the same KB (e.g. document updated twice quickly); a previous batch still running long (LLM calls) when a new trigger fires; multiple workers without distributed locking racing on one KB.
Related errors
- enqueue wiki ingest trigger: task enqueuer is nil
- LLM returned nil response
- wiki page slug is required
- knowledge_base_id is required
- cannot revert to the current version
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/ddb6d704e9e99ac8.
Report an issue: GitHub.