yikart/AiToEarn · error · BadRequestException
Invalid public upload id
Error message
Invalid public upload id
What it means
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.
Source
Thrown at project/aitoearn-backend/libs/assets/src/http/assets-http.controller-base.ts:19
import type { Response } from 'express'
import { BadRequestException, Body, Get, Inject, Param, Post, Query, Res } from '@nestjs/common'
import { GetToken, Public, TokenInfo } from '@yikart/aitoearn-auth'
import { ApiDoc, UserType } from '@yikart/common'
import { AssetStatus } from '@yikart/mongodb'
import * as mime from 'mime-types'
import { AssetsService } from '../assets.service'
import { VideoMetadataService } from '../video-metadata.service'
import { AssetVo } from '../vo/asset.vo'
import { ThumbnailResultVo } from '../vo/thumbnail-result.vo'
import { UploadResultVo } from '../vo/upload-result.vo'
import { CreateUploadSignDto, GetThumbnailQueryDto, OssCallbackDto } from './assets-http.dto'
import { ASSETS_HTTP_OPTIONS, AssetsHttpModuleOptions } from './assets-http.options'
const PUBLIC_UPLOAD_ID_PATTERN = /^[\w-]{8,64}$/
function toPublicUploadUserId(publicUploadId: string) {
if (!PUBLIC_UPLOAD_ID_PATTERN.test(publicUploadId)) {
throw new BadRequestException('Invalid public upload id')
}
return `public-${publicUploadId}`
}
export abstract class AssetsHttpControllerBase {
protected readonly userType: UserType
constructor(
protected readonly assetsService: AssetsService,
protected readonly videoMetadataService: VideoMetadataService,
@Inject(ASSETS_HTTP_OPTIONS) options: AssetsHttpModuleOptions,
) {
this.userType = options.userType ?? UserType.User
}
@ApiDoc({
summary: 'Create Upload Signed URL',View on GitHub (pinned to d3aa8bea5b)
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
Example fix
// before
const id = `${userId}:${Date.now()}` // ':' not allowed
// after
const id = crypto.randomUUID().replace(/-/g, '') // 32 chars, matches [\w-]{8,64}
const res = await api.post(`/assets/public/${id}/upload`) Defensive patterns
Strategy: validation
Validate before calling
const PUBLIC_UPLOAD_ID_RE = /^[\w-]{8,64}$/
if (!PUBLIC_UPLOAD_ID_RE.test(publicUploadId)) throw new Error('public upload id must be 8-64 chars of [A-Za-z0-9_-]') Type guard
function isValidPublicUploadId(id: unknown): id is string {
return typeof id === 'string' && /^[\w-]{8,64}$/.test(id)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- accountId和视频大小是必须的
- video duration is required
- OpenAI does not support multiple images
- image_tail requires a single first frame image
- content is required
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/af993379cf95a0bb.
Report an issue: GitHub.