linshenkx/prompt-optimizer · error · EvaluationValidationError
${label} #${index + 1} must not provide both assetId and b64
Error message
${label} #${index + 1} must not provide both assetId and b64. What it means
The mirror of the previous rule: a media item must not supply both assetId and b64, because the service cannot decide which source of truth to use for the image. Validation throws when both fields are non-empty on the same item.
Source
Thrown at packages/core/src/services/evaluation/service.ts:1685
private validateMediaItems(mediaItems: EvaluationMediaItem[], label: string): void {
mediaItems.forEach((item, index) => {
const itemLabel = item?.label?.trim() || '';
const assetId = item?.assetId?.trim() || '';
const b64 = item?.b64?.trim() || '';
if (!itemLabel) {
throw new EvaluationValidationError(`${label} #${index + 1} label must not be empty.`);
}
if (!assetId && !b64) {
throw new EvaluationValidationError(
`${label} #${index + 1} must provide either assetId or b64.`
);
}
if (assetId && b64) {
throw new EvaluationValidationError(
`${label} #${index + 1} must not provide both assetId and b64.`
);
}
});
}
private validateContentBlock(
block: EvaluationContentBlock | undefined,
label: string
): void {
if (!block) {
throw new EvaluationValidationError(`${label} must not be empty.`);
}
if (!block.label?.trim()) {
throw new EvaluationValidationError(`${label} label must not be empty.`);
}
const hasContent = !!block.content?.trim();
const hasMedia = this.hasBlockMedia(block);View on GitHub (pinned to 3e677b1d9f)
Solutions
- Keep exactly one of assetId or b64 on the media item and delete the other
- Prefer assetId for large/stored images and b64 only for small inline payloads
- Strip the unused field in a pre-submit sanitizer
Example fix
// before
media: [{ label: 'img', assetId: 'img-1', b64: base64String }]
// after
media: [{ label: 'img', assetId: 'img-1' }] Defensive patterns
Strategy: validation
Validate before calling
function pickOneSource(item: { label: string; assetId?: string; b64?: string }) {
return item.assetId?.trim()
? { label: item.label, assetId: item.assetId }
: { label: item.label, b64: item.b64 };
}
const sanitized = media.map(pickOneSource); Type guard
null
Try / catch
try {
await evaluationService.create(request);
} catch (err) {
if (err instanceof EvaluationValidationError && /must not provide both/.test(err.message)) {
request = stripConflictingFields(request); // keep assetId, drop b64
} else throw err;
} Prevention
- Strip b64 whenever you set assetId (and vice versa) at construction time
- Use one code path per source mechanism instead of merging objects
- Sanitize payloads before submit
When it happens
Trigger: A media item whose assetId and b64 are both non-empty strings. Typically introduced when code sets b64 as a default and then also assigns an assetId (or vice versa).
Common situations: Migrating from b64 to assetId-based flow without clearing the old field; spread-merging objects that accidentally combine both; form UI that populates both inputs.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- ${label} #${index + 1} label must not be empty.
- ${label} #${index + 1} must provide either assetId or b64.
- Result evaluation snapshot testCaseId must match testCase.id
- Image result evaluation requires at least one output image e
- Compare evaluation requires at least one test case.
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/3219ef89d51b45c0.
Report an issue: GitHub.