passbolt/passbolt_api · error · CustomValidationException
400
400
Error message
Could not validate tags data.
What it means
TagsTable::buildEntitiesOrFail validates a batch of tag payloads and aggregates per-entity validation errors. When any entity in the collection fails CakePHP validation, it throws CustomValidationException with this message and the indexed error map. It is the batch-level guard so clients see all failing rows at once.
Solutions
- Inspect the error map in the exception payload: keys are array indexes of the failing tags, values are the field validation errors.
- Fix the offending slug(s) in the failing indexes (trim, shorten to allowed length, keep allowed charset).
- Ensure shared tags start with '#' and personal tags do not.
- Retry with only valid tag payloads.
Example fix
// before
PATCH tags: [{"slug":""},{"slug":"release#1"}]
// after
PATCH tags: [{"slug":"release-1"}] Defensive patterns
Strategy: validation
Validate before calling
$errors = [];
foreach ($tagPayloads as $i => $p) {
$slug = trim($p['slug'] ?? '');
if ($slug === '' || mb_strlen($slug) > 128) { $errors[$i] = ['slug' => 'invalid']; }
}
if ($errors) { throw new \InvalidArgumentException(json_encode($errors)); } Type guard
function isValidTagSlug(mixed $slug): bool {
return is_string($slug) && trim($slug) !== '' && mb_strlen(trim($slug)) <= 128;
} Try / catch
try {
$tags = $tagsTable->buildEntitiesOrFail($payloads);
} catch (CustomValidationException $e) {
foreach ($e->getErrors() as $idx => $fieldErrors) {
$this->log("Tag at index $idx failed: " . json_encode($fieldErrors));
}
} Prevention
- Trim and length-check slugs before submitting
- Keep '#' prefix only on shared tags
- Validate with the same rules client-side
- Strip unknown fields from payloads
When it happens
Trigger: POST/PUT to the tags endpoint with an array of tag payloads where at least one slug fails validation (empty slug, slug exceeding max length, invalid characters, or non-permitted fields).
Common situations: Client sends tags with empty strings, overly long slugs (e.g. >128 chars pasted from elsewhere), or mixed personal/shared ('#' prefix) tags with invalid formats; API consumers not trimming whitespace before submitting.
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
- " " is not a valid search filter.
- " " is not a valid search filter. It is not a UTF8 string.
- " " is not a valid search filter. It should be between 1…
- " " is not a valid user filter.
- " " is not a valid value for filter .
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/c049f8df39017a8c.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Tags/src/Model/Table/TagsTable.php:438
try {
$collection[$i] = $this->buildEntityOrFail($dto);
// If not shared, add the user_id in the resources_tags join table
$resourceTagUserId = null;
if ($dto->isPersonal()) {
$resourceTagUserId = $userId;
}
$collection[$i]['_joinData'] = $this->ResourcesTags->newEntity(
['user_id' => $resourceTagUserId],
['accessibleFields' => ['user_id' => true]]
);
} catch (CustomValidationException $e) {
$errors[$i] = $e->getErrors();
}
}
if (!empty($errors)) {
throw new CustomValidationException(__('Could not validate tags data.'), $errors);
}
return $collection;
}
/**
* @param \Passbolt\Tags\Model\Dto\MetadataTagDto $dto DTO.
* @return \Passbolt\Tags\Model\Entity\Tag
* @throws \App\Error\Exception\CustomValidationException When there are errors building entity object.
*/
public function buildEntityOrFail(MetadataTagDto $dto): Tag
{
$tag = $dto->toArray();
if ($dto->isV5()) {
$data = [
'metadata' => $tag['metadata'],
'metadata_key_id' => $tag['metadata_key_id'],View on GitHub (pinned to 31c1bbc10f)