{"record":{"id":"95a5332116fe6c8c","repo":"thedotmack/claude-mem","slug":"server-job-id-must-not-contain-got-jobid","errorCode":null,"errorMessage":"server job ID must not contain ':' (got ${jobId})","messagePattern":"server job ID must not contain ':' \\(got (.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/server/jobs/ServerJobQueue.ts","lineNumber":141,"sourceCode":"      : new Queue<TPayload>(this.name, queueOptions);\n    return this.queue;\n  }\n\n  private async addToQueue(jobId: string, payload: TPayload, options?: JobsOptions): Promise<void> {\n    await (this.getQueue().add as (\n      name: string,\n      data: TPayload,\n      opts?: JobsOptions\n    ) => Promise<unknown>)(this.name, payload, {\n      ...this.defaultJobOptions,\n      ...options,\n      jobId\n    });\n  }\n\n  async add(jobId: string, payload: TPayload, options?: JobsOptions): Promise<void> {\n    if (jobId.includes(':')) {\n      throw new Error(`server job ID must not contain ':' (got ${jobId})`);\n    }\n    try {\n      await this.addToQueue(jobId, payload, options);\n    } catch (error) {\n      const err = error instanceof Error ? error : new Error(String(error));\n      throw this.toRedisUnavailableError(err);\n    }\n  }\n\n  async getJob(jobId: string): Promise<Job<TPayload> | null | undefined> {\n    try {\n      return (await this.getQueue().getJob(jobId)) as Job<TPayload> | null | undefined;\n    } catch (error) {\n      const err = error instanceof Error ? error : new Error(String(error));\n      throw this.toRedisUnavailableError(err);\n    }\n  }\n","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/server/jobs/ServerJobQueue.ts#L123-L159","documentation":"ServerJobQueue.add() validates job IDs before enqueueing into BullMQ. Redis/BullMQ job IDs are used in key names, and ':' is the key separator, so an ID containing ':' would corrupt key structure. The queue rejects such IDs up front with this error.","triggerScenarios":"Calling add(jobId, payload, options) with a jobId string that includes the ':' character, e.g. 'tenant:123:job' or a composite 'type:id' identifier.","commonSituations":"Building composite IDs by joining tenant/user IDs with ':'; passing a Redis key or BullMQ queue name as the jobId; using a serialized object string containing colons as an ID.","solutions":["Remove or replace ':' in the jobId before calling add (e.g. use '-' or '_' as separator)","Use a library-provided sanitizer/encoder such as encodeURIComponent or a hash of the composite parts","If a composite identifier is needed, pass its parts in the job payload instead of the ID"],"exampleFix":"// before\nawait queue.add(`${tenantId}:${jobType}:${uuid}`, payload);\n// after\nawait queue.add(`${tenantId}--${jobType}--${uuid}`, payload);","handlingStrategy":"validation","validationCode":"if (typeof jobId === 'string' && !jobId.includes(':')) {\n  await queue.add(jobId, payload, options);\n} else {\n  throw new Error(`jobId must not contain ':': ${jobId}`);\n}","typeGuard":"const isSafeJobId = (id: unknown): id is string =>\n  typeof id === 'string' && id.length > 0 && !id.includes(':');","tryCatchPattern":"try {\n  await queue.add(jobId, payload, options);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"must not contain ':'\")) {\n    // sanitize and retry or log a config error\n  }\n  throw e;\n}","preventionTips":["Derive job IDs from a single safe alphabet (UUIDs, hex)","Join composite key parts with '-' or '_' instead of ':'","Add a unit test asserting generated IDs contain no ':'"],"tags":["validation","jobs","redis","identifier"],"backgroundTag":"invalid-identifier-format","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}