passbolt/passbolt_api · error · BadRequestException

The resource identifier should be a valid UUID.

Error message

The resource identifier should be a valid UUID.

What it means

CommentsAddService::add() validates that the resource identifier (foreignKey, i.e. the resource the comment is attached to) is a well-formed UUID using Cake's Validation::uuid() before doing anything else. A malformed id is rejected early with a 400 to avoid pointless DB work. It says nothing about whether the resource actually exists — that is checked later.

Solutions

  1. Inspect the request URL/payload and replace the identifier with the resource's actual UUID.
  2. Check the client is reading the id from the correct response field (e.g. resource.id, not resource.slug).
  3. Validate ids client-side with a UUID regex before sending.

Example fix

// before
await fetch(`/comments/${resource.slug}/comments`, {method: 'POST'})
// after
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(resource.id)) throw new Error('invalid resource id');
await fetch(`/comments/${resource.id}/comments`, {method: 'POST'})
Defensive patterns

Strategy: validation

Validate before calling

const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
if (!UUID_RE.test(resourceId)) throw new Error(`resourceId is not a UUID: ${resourceId}`);

Type guard

function isUuid(v) { return typeof v === 'string' && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v); }

Try / catch

try { await addComment(resourceId, data); }
catch (e) { if (e.response?.status === 400) console.error('Bad resource id:', resourceId); else throw e; }

Prevention

When it happens

Trigger: POST /comments/{resourceId}/comments (or POST /comments with resourceId in payload) where resourceId is not a 36-char UUID — e.g. a slug, an integer id, an empty string, or a truncated id.

Common situations: Client-side code concatenating route fragments incorrectly; using a legacy numeric id from an old database; copy-paste dropping characters; sending 'me' or other placeholder tokens as the resource id.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/9290a526eb9df99e. Report an issue: GitHub.

Appendix: source

Thrown at src/Service/Comments/CommentsAddService.php:64

     */
    public function __construct()
    {
        $this->Comments = TableRegistry::getTableLocator()->get('Comments');
    }

    /**
     * Create a new comment for a resource.
     *
     * @param \App\Utility\UserAccessControl $uac The user access control
     * @param string $foreignKey The identifier of the resource to add a comment to
     * @param array $data The comment data
     * @return \App\Model\Entity\Comment $comment comment entity
     * @throws \Cake\Http\Exception\InternalErrorException if the comment couldn't be saved
     */
    public function add(UserAccessControl $uac, string $foreignKey, array $data): Comment
    {
        if (!Validation::uuid($foreignKey)) {
            throw new BadRequestException(__('The resource identifier should be a valid UUID.'));
        }

        $comment = $this->_buildAndValidateCommentEntity($uac, $foreignKey, $data);
        $this->_handleValidationErrors($comment);

        if (!$this->Comments->save($comment)) {
            $this->_handleValidationErrors($comment);
            $oops = __('Could not save the comment, please try again later.');
            throw new InternalErrorException($oops);
        }
        $this->_notifyUsers($comment);

        return $comment;
    }

    /**
     * Manage validation errors.
     *

View on GitHub (pinned to 31c1bbc10f)