yikart/AiToEarn · error · AppException
ResponseCode.AssetNotFound
ResponseCode.AssetNotFound
Error message
AssetNotFound
What it means
confirmUpload throws AssetNotFound when assetRepository.getById(dto.assetId) returns no asset. The client is confirming an upload whose pending-asset record does not exist in the database.
Source
Thrown at project/aitoearn-backend/libs/assets/src/assets.service.ts:201
mimeType: dto.mimeType,
filename: dto.filename,
metadata: dto.metadata,
})
return {
asset,
url: this.buildUrl(path),
}
}
async confirmUpload(dto: ConfirmAssetDto): Promise<Asset> {
if (this.options.maxSize != null && dto.size && dto.size >= this.options.maxSize) {
throw new AppException(ResponseCode.AssetTooLarge)
}
const asset = await this.assetRepository.getById(dto.assetId)
if (!asset) {
throw new AppException(ResponseCode.AssetNotFound)
}
if (asset.status !== AssetStatus.Pending) {
return asset
}
const updateData: Partial<Asset> = {
status: AssetStatus.Confirmed,
}
if (dto.size) {
updateData.size = dto.size
}
if (dto.metadata) {
updateData.metadata = { ...asset.metadata, ...dto.metadata }
}
View on GitHub (pinned to d3aa8bea5b)
Solutions
- Verify dto.assetId matches a real asset row; re-run the upload-sign flow to obtain a fresh id
- Check you are pointing at the correct database/environment
- Handle AssetNotFound client-side by restarting the upload flow instead of retrying the same id
- Log the assetId and query the asset table directly to confirm deletion
Example fix
// before
await confirmUpload({ assetId: staleId, size })
// after
const { assetId } = await createUploadSign(userId, dto)
await doUpload(assetId)
await confirmUpload({ assetId, size }) Defensive patterns
Strategy: try-catch
Validate before calling
const asset = await assetsApi.get(assetId) // or check the id exists locally
if (!asset) throw new Error(`assetId ${assetId} unknown; re-run upload sign flow`) Type guard
function isNonEmptyUuid(id: unknown): id is string {
return typeof id === 'string' && /^[0-9a-f-]{36}$/i.test(id)
} Try / catch
try {
await confirmUpload({ assetId, size })
} catch (e) {
if (e.code === ResponseCode.AssetNotFound) {
const sign = await createUploadSign(userId, dto)
await doUpload(sign)
await confirmUpload({ assetId: sign.assetId, size })
} else throw e
} Prevention
- Always obtain assetId from a fresh createUploadSign call, never cache across sessions
- Don't share assetIds between environments
- Clean up pending assets with a TTL long enough for slow clients
- Log assetId on confirm failures to speed diagnosis
When it happens
Trigger: Confirming with an assetId that was never created, was deleted, belongs to another environment/database, or a stale id cached client-side after the record was cleaned up.
Common situations: Retrying an old confirm call after the asset record expired/was purged, copying assetId between dev and prod, typo'd UUID, or the sign step actually failed earlier so no record exists.
Related errors
- ResponseCode.AssetTooLarge
- 任务不存在
- VideoUploadVidNotFound
- Relay uploadSign returned no uploadUrl: ${JSON.stringify(sig
- InvalidAiTaskId
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/8778678d474f00a2.
Report an issue: GitHub.