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 dead

View on GitHub (pinned to 988cbb0330)

Solutions

  1. No action needed — the executor retries with wikiIngestRetryDelay until the active batch releases the lock.
  2. Reduce duplicate triggers by debouncing wiki ingest enqueues per KB.
  3. 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

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


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