yikart/AiToEarn · error · BadRequestException
userId is required
Error message
userId is required
What it means
generation() destructures the per-user info from ImageGenerationDto and requires it to run the generation with billing/attribution. When request.user is absent it throws BadRequestException('userId is required') before calling any model. This is a guard against unauthenticated or mis-shaped requests reaching expensive image generation.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-ai/src/core/ai/image/image.service.ts:124
const contentType = imageUrlOrResponse.headers.get('content-type') || 'image/png'
const buffer = Buffer.from(await imageUrlOrResponse.arrayBuffer())
const result = await this.assetsService.uploadFromBuffer(userId, buffer, {
type: AssetType.AiImage,
mimeType: contentType,
}, subPath)
return result.asset.path
}
}
/**
* 图片生成
*/
async generation(request: ImageGenerationDto) {
const { user, ...params } = request
const runtimeModel = this.resolveRuntimeImageModel(params.model, 'generation')
if (!user) {
throw new BadRequestException('userId is required')
}
if (runtimeModel === 'gpt-image-1') {
delete params.response_format
delete params.style
}
const result = await this.openaiService.createImageGeneration({
...params,
model: runtimeModel,
} as Omit<OpenAI.Images.ImageGenerateParams, 'user'> & { apiKey?: string })
for (const image of result.data || []) {
if (image.url) {
image.url = await this.uploadImageToS3(image.url, user, `${request.model}`)
}
if (image.b64_json) {
const mimeType = `image/${result.output_format || 'png'}`View on GitHub (pinned to d3aa8bea5b)
Solutions
- Ensure the caller is authenticated so the user object is attached to ImageGenerationDto before calling generation()
- If calling the service directly, populate request.user from your auth context (userId, userType)
- Check middleware/guards that extract the user; a silent failure there yields user === undefined
- Wrap callers like userGeneration so a missing user short-circuits with a clear 401/400 rather than reaching this point
Example fix
// before
await imageService.generation({ model: 'gpt-image-1', prompt })
// after
await imageService.generation({ model: 'gpt-image-1', prompt, user: { userId: ctx.userId, userType: ctx.userType } }) Defensive patterns
Strategy: validation
Validate before calling
function requireUser(dto: ImageGenerationDto) {
if (!dto.user?.userId) throw new Error('user (with userId) must be provided for image generation')
return dto
} Type guard
function hasUser(dto: ImageGenerationDto): dto is ImageGenerationDto & { user: NonNullable<ImageGenerationDto['user']> } {
return !!dto.user && typeof dto.user.userId === 'string' && dto.user.userId.length > 0
} Try / catch
try {
await imageService.generation(dto)
} catch (e) {
if (e instanceof BadRequestException && e.message === 'userId is required') {
throw new UnauthorizedException('Authentication required for image generation')
}
throw e
} Prevention
- Build the DTO from an authenticated request context, never from raw client body alone
- Ensure auth guards run before the controller populates user
- In internal calls/tests, always populate user: { userId, userType }
- Add a constructor-level validation (class-validator @IsDefined on user) to fail early
When it happens
Trigger: An API call to the image generation endpoint omits the user object in the request body, an internal caller (e.g. userGeneration path via MCP/agent tools) forwards a DTO built without user info, or auth middleware failed to attach the user but the route was still invoked.
Common situations: Calling the service internally (not via the controller) and forgetting to populate user; token/auth issues causing the user field to be dropped; DTO constructed manually in tests or scripts without user.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- videoId, userId和accountId是必须的
- token和mail是必须的
- userId和accountId是必须的
- No subtitle entries in response
- No response from Gemini
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/3e56df0d4a72c43b.
Report an issue: GitHub.