flarum/framework · error · BadRequestException

relationship does not include data key

Error message

relationship does not include data key

What it means

Thrown in ToOne::deserializeValue when a client writes a to-one relationship whose JSON:API value is not an object containing a 'data' member. Flarum/tobyz-json-api-server requires relationship documents to be {data: ...}; anything else (string, number, missing 'data' key) cannot be interpreted as a resource identifier or null, so the request is rejected as a 400 Bad Request.

Solutions

  1. Send the relationship value as an object with a 'data' member, e.g. {"data": {"type": "users", "id": "1"}}
  2. Use {"data": null} to clear the to-one relationship
  3. Ensure the request body is valid JSON:API so 'data' parses as an array in PHP
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at framework/core/src/Api/Schema/Relationship/ToOne.php:29 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of flarum/framework@4b939f6853 (2026-09-15). Data as JSON: /api/errors/5b2727f47db5c0a9. Report an issue: GitHub.

Appendix: source

Thrown at framework/core/src/Api/Schema/Relationship/ToOne.php:29

use Flarum\Api\Schema\Concerns\FlarumRelationship;
use Tobyz\JsonApiServer\Context;
use Tobyz\JsonApiServer\Exception\BadRequestException;
use Tobyz\JsonApiServer\Exception\Sourceable;
use Tobyz\JsonApiServer\Laravel\Field\ToOne as BaseToOne;

class ToOne extends BaseToOne
{
    use FlarumRelationship;

    public function deserializeValue(mixed $value, Context $context): mixed
    {
        if ($this->deserializer) {
            return ($this->deserializer)($value, $context);
        }

        if (! is_array($value) || ! array_key_exists('data', $value)) {
            throw new BadRequestException('relationship does not include data key');
        }

        if ($value['data'] === null) {
            return null;
        }

        if (count($this->collections) === 1) {
            $value['data']['type'] ??= $this->collections[0];
        }

        try {
            return $this->findResourceForIdentifier($value['data'], $context);
        } catch (Sourceable $e) {
            throw $e->prependSource(['pointer' => '/data']);
        }
    }
}

View on GitHub (pinned to 4b939f6853)