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

  1. Inspect the error map in the exception payload: keys are array indexes of the failing tags, values are the field validation errors.
  2. Fix the offending slug(s) in the failing indexes (trim, shorten to allowed length, keep allowed charset).
  3. Ensure shared tags start with '#' and personal tags do not.
  4. 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

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


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)