TencentCloud/TencentDB-Agent-Memory · error
[skill-worker-pool] concurrency must be positive integer, go
Error message
[skill-worker-pool] concurrency must be positive integer, got ${opts.concurrency} What it means
SkillWorkerPool validates its options in the constructor and refuses to build a pool whose concurrency is not a positive integer. This is a fail-fast programming-error guard: a pool with 0, negative, fractional, or NaN concurrency cannot run worker loops meaningfully.
Source
Thrown at MemoryCore/src/core/skill/conversation-add/worker-pool.ts:99
* 2026-08-03 crash-recovery §4.5: 降级路径下周期性自愈扫描的间隔 ms。
* 只在 queue.getPeekStrategy() === "rpop_lpush_downgrade" 时启用。默认 60_000。
* 非降级路径下 start() 只跑一次冷启动扫描, 不启动定时器。
*/
selfHealIntervalMs?: number;
}
export class SkillWorkerPool {
private readonly opts: SkillWorkerPoolOptions;
private readonly logger: ExtractorLogger;
private readonly poolId: string;
private closed = false;
private started = false;
private loopPromises: Promise<void>[] = [];
private selfHealTimer: ReturnType<typeof setInterval> | undefined;
constructor(opts: SkillWorkerPoolOptions) {
if (!Number.isInteger(opts.concurrency) || opts.concurrency < 1) {
throw new Error(`[skill-worker-pool] concurrency must be positive integer, got ${opts.concurrency}`);
}
this.opts = opts;
this.logger = opts.logger;
this.poolId = opts.poolId ?? `skill-pool-${process.pid}`;
}
start(): void {
if (this.started) return;
this.started = true;
this.closed = false;
const n = this.opts.concurrency;
this.logger.info(
`[skill-worker-pool] start pool_id=${this.poolId} concurrency=${n} ` +
`brpopBlockMs=${this.opts.brpopBlockMs ?? 5000} ` +
`extractLockTtlMs=${this.opts.extractLockTtlMs ?? 600_000}`,
);
// 2026-08-03 crash-recovery §4.5: 冷启动跑一次 selfHealScan, 清历史遗留的View on GitHub (pinned to 3efcd317b8)
Solutions
- Pass an explicit positive integer: validate before constructing (Number.isInteger(n) && n >= 1)
- Sanitize env-derived values with a fallback: const c = Number.parseInt(raw) || defaultConcurrency
- Math.round/floor any computed concurrency and clamp to at least 1
- Fix the config source so concurrency is actually provided
Example fix
// before
const pool = new SkillWorkerPool({ concurrency: Number(process.env.WORKERS), ... });
// after
const workers = Math.max(1, Math.floor(Number(process.env.WORKERS) || 4));
const pool = new SkillWorkerPool({ concurrency: workers, ... }); Defensive patterns
Strategy: validation
Validate before calling
function assertPositiveInt(n: unknown): asserts n is number {
if (!Number.isInteger(n) || (n as number) < 1)
throw new Error(`concurrency must be a positive integer, got ${n}`);
}
assertPositiveInt(opts.concurrency); Type guard
function isValidConcurrency(v: unknown): v is number {
return typeof v === "number" && Number.isInteger(v) && v >= 1;
} Try / catch
let pool: SkillWorkerPool;
try {
pool = new SkillWorkerPool(opts);
} catch (e) {
if (e instanceof Error && e.message.includes("concurrency must be positive integer")) {
pool = new SkillWorkerPool({ ...opts, concurrency: 4 });
} else throw e;
} Prevention
- Sanitize env-derived numbers: Math.max(1, Math.floor(Number(raw) || DEFAULT))
- Never pass possibly-NaN values straight from config into constructors
- Validate the whole options object at config-load time, not at pool construction
- Add a startup smoke test that constructs the pool with production config
When it happens
Trigger: new SkillWorkerPool({ concurrency: 0 }), concurrency: -2, a fractional value like 2.5, NaN coming from an unparsed env var (Number.parseInt returning NaN), or undefined when the caller relies on a default that was never applied.
Common situations: Reading worker count from env/config (e.g. WORKER_CONCURRENCY) without validating the parsed number; arithmetic producing NaN; copy-pasted config where concurrency was commented out; dynamic sizing code computing 0 when the queue is empty.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- EmbeddingService: dimensions is required for remote provider
- llm.provider=proxy 且 useMemorySystemUserKey=false 时必须显式 llm.
- teamId is required for an agent prompt setting
- EmbeddingService: apiKey is required for remote provider
- EmbeddingService: baseUrl is required for remote provider
AI-assisted analysis of TencentCloud/TencentDB-Agent-Memory@3efcd317b8 (2026-09-01).
Data as JSON: /api/errors/43c6dffb27605953.
Report an issue: GitHub.