{"record":{"id":"af993379cf95a0bb","repo":"yikart/AiToEarn","slug":"invalid-public-upload-id","errorCode":null,"errorMessage":"Invalid public upload id","messagePattern":"Invalid public upload id","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-backend/libs/assets/src/http/assets-http.controller-base.ts","lineNumber":19,"sourceCode":"import type { Response } from 'express'\nimport { BadRequestException, Body, Get, Inject, Param, Post, Query, Res } from '@nestjs/common'\nimport { GetToken, Public, TokenInfo } from '@yikart/aitoearn-auth'\nimport { ApiDoc, UserType } from '@yikart/common'\nimport { AssetStatus } from '@yikart/mongodb'\nimport * as mime from 'mime-types'\nimport { AssetsService } from '../assets.service'\nimport { VideoMetadataService } from '../video-metadata.service'\nimport { AssetVo } from '../vo/asset.vo'\nimport { ThumbnailResultVo } from '../vo/thumbnail-result.vo'\nimport { UploadResultVo } from '../vo/upload-result.vo'\nimport { CreateUploadSignDto, GetThumbnailQueryDto, OssCallbackDto } from './assets-http.dto'\nimport { ASSETS_HTTP_OPTIONS, AssetsHttpModuleOptions } from './assets-http.options'\n\nconst PUBLIC_UPLOAD_ID_PATTERN = /^[\\w-]{8,64}$/\n\nfunction toPublicUploadUserId(publicUploadId: string) {\n  if (!PUBLIC_UPLOAD_ID_PATTERN.test(publicUploadId)) {\n    throw new BadRequestException('Invalid public upload id')\n  }\n\n  return `public-${publicUploadId}`\n}\n\nexport abstract class AssetsHttpControllerBase {\n  protected readonly userType: UserType\n\n  constructor(\n    protected readonly assetsService: AssetsService,\n    protected readonly videoMetadataService: VideoMetadataService,\n    @Inject(ASSETS_HTTP_OPTIONS) options: AssetsHttpModuleOptions,\n  ) {\n    this.userType = options.userType ?? UserType.User\n  }\n\n  @ApiDoc({\n    summary: 'Create Upload Signed URL',","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/libs/assets/src/http/assets-http.controller-base.ts#L1-L37","documentation":"BadRequestException('Invalid public upload id') is thrown by toPublicUploadUserId when the supplied publicUploadId does not match /^\\w-]{8,64}$/ — i.e. it must be 8–64 characters of letters, digits, underscore, or hyphen. The ID is used to synthesize an isolated 'public-<id>' user for anonymous public uploads, so malformed IDs are rejected before touching the assets service.","triggerScenarios":"Calling public upload endpoints (via userId getter) with an ID shorter than 8 chars, longer than 64, or containing characters outside [A-Za-z0-9_-] such as ':', '@', spaces, or Mongo ObjectIds with invalid chars (ObjectIds are hex, so usually length is the issue), or an empty/undefined ID.","commonSituations":"Client generates its own upload session ID with UUIDs containing braces or uses a JWT/email as the ID; ID truncated by URL encoding; version change where old clients send shorter tokens.","solutions":["Generate the public upload ID as an 8–64 char alphanumeric/underscore/hyphen string (e.g. crypto.randomUUID().replace(/-/g,'') or nanoid)","Validate the ID format client-side before calling the endpoint","Strip or re-encode characters that URL encoding may have altered","Use the ID exactly as returned by the public-upload-initiation endpoint instead of constructing one"],"exampleFix":"// before\nconst id = `${userId}:${Date.now()}` // ':' not allowed\n// after\nconst id = crypto.randomUUID().replace(/-/g, '') // 32 chars, matches [\\w-]{8,64}\nconst res = await api.post(`/assets/public/${id}/upload`)","handlingStrategy":"validation","validationCode":"const PUBLIC_UPLOAD_ID_RE = /^[\\w-]{8,64}$/\nif (!PUBLIC_UPLOAD_ID_RE.test(publicUploadId)) throw new Error('public upload id must be 8-64 chars of [A-Za-z0-9_-]')","typeGuard":"function isValidPublicUploadId(id: unknown): id is string {\n  return typeof id === 'string' && /^[\\w-]{8,64}$/.test(id)\n}","tryCatchPattern":null,"preventionTips":["Generate IDs with crypto.randomUUID().replace(/-/g,'') or nanoid","Never embed ':', '@', or whitespace in upload IDs","Validate format client-side before the HTTP call","Use server-returned IDs rather than constructing your own"],"tags":["validation","http","bad-request","upload"],"backgroundTag":"invalid-identifier-format","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}