{"record":{"id":"7332337a47537cff","repo":"yikart/AiToEarn","slug":"invalidworklink-733233","errorCode":"InvalidWorkLink","errorMessage":"InvalidWorkLink","messagePattern":"InvalidWorkLink","errorType":"error_code","errorClass":"AppException","httpStatus":null,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/rednote/rednote-publish.provider.ts","lineNumber":66,"sourceCode":"          params: { field: PublishValidationField.Option },\n        }],\n      }\n    }\n\n    return { valid: true }\n  }\n\n  async normalize(input: PublishNormalizeInput<RedNoteOption>): Promise<NormalizedPublishTask<RedNoteOption>> {\n    return {\n      content: input.content,\n      option: input.option,\n    }\n  }\n\n  async publish(input: PublishPublishInput<RedNoteOption>): Promise<PublishProviderResult<RedNoteDataOption>> {\n    const workLink = input.option?.workLink\n    if (!workLink) {\n      throw new AppException(ResponseCode.InvalidWorkLink)\n    }\n\n    const workLinkInfo = await this.workProvider.getWorkLinkInfo(workLink)\n    const extra = workLinkInfo.extra\n\n    return {\n      status: 200,\n      platformWorkId: extra.dataId,\n      permalink: extra.resolvedUrl ?? workLink,\n      originalWorkLink: extra.originalWorkLink,\n      workStatus: extra.workStatus,\n      dataOption: {\n        dataId: extra.dataId,\n        uniqueId: extra.uniqueId,\n      },\n    }\n  }\n}","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/rednote/rednote-publish.provider.ts#L48-L84","documentation":"RedNote publish requires input.option.workLink: without it there is no source note to publish from, so the provider throws InvalidWorkLink before doing any work. It is a synchronous input-validation error thrown from the publish entry point.","triggerScenarios":"Calling rednotePublishProvider.publish with input.option undefined, or option present but option.workLink missing/null/empty.","commonSituations":"Caller builds PublishPublishInput without populating the RedNote-specific option; upstream job lost the workLink field; caller confused workLink with a plain note URL stored elsewhere; schema change on the producer side dropped the field.","solutions":["Ensure the publishing request includes option.workLink with the full RedNote note URL.","Validate the input payload at the API/job boundary before invoking publish (require non-empty workLink for RedNote).","Check where the PublishPublishInput is constructed in your flow — the workLink is likely dropped during serialization or option construction."],"exampleFix":"// before\nawait provider.publish({ ...rest, option: undefined })\n// after\nif (!rest.option?.workLink) {\n  throw new Error('RedNote publish requires option.workLink')\n}\nawait provider.publish({ ...rest, option: rest.option })","handlingStrategy":"validation","validationCode":"function assertRedNotePublishInput(input: PublishPublishInput<RedNoteOption>) {\n  if (!input.option?.workLink) {\n    throw new Error('RedNote publish requires a non-empty option.workLink')\n  }\n}","typeGuard":"function hasWorkLink(opt: RedNoteOption | undefined | null): opt is RedNoteOption & { workLink: string } {\n  return typeof opt?.workLink === 'string' && opt.workLink.length > 0\n}","tryCatchPattern":"try {\n  await provider.publish(input)\n} catch (e) {\n  if (e instanceof AppException && e.code === ResponseCode.InvalidWorkLink) {\n    return { ok: false, reason: 'missing workLink in publish option' }\n  }\n  throw e\n}","preventionTips":["Validate publish payloads against a schema (zod/class-validator) at the API boundary.","Make workLink a required field in the RedNote publish DTO.","Add a unit test asserting publish throws without workLink.","Check serialization of options when queuing publish jobs."],"tags":["validation","input-validation","rednote","publish"],"backgroundTag":"missing-required-field","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}