flarum/framework · error · ValidationException

str_replace(':attribute', 'users'…

Error message

str_replace(':attribute', 'users', $this->translator->trans('validation.required'))

What it means

When creating a dialog message without dialog_id, the resource checks the 'users' attribute for valid recipient ids (excluding the actor); if the resulting list is empty it throws a ValidationException on the 'users' field with the translated 'required' message. The odd message string shown is the raw translation call that generates the text.

Solutions

  1. Include attributes.users with at least one valid user id other than the sender.
  2. Provide dialog_id to send into an existing dialog instead of creating a new one.
  3. Ensure ids in the users array are integers/strings of existing users and not empty values.
  4. Verify the frontend sends the recipients under data.attributes.users.

Example fix

// before
{ "attributes": { "content": "hi", "users": [] } }
// after
{ "attributes": { "content": "hi", "users": [{ "id": 7 }] } }
Defensive patterns

Strategy: validation

Validate before calling

const users = (attrs.users ?? []).map(u => u.id).filter(id => id && id !== currentUserId); if (!attrs.dialog_id && users.length === 0) { /* require recipients before submit */ }

Try / catch

try { await store.createRecord('dialog-messages', payload).save(); } catch (e) { if (e.errors?.users) show('Select at least one recipient'); }

Prevention

When it happens

Trigger: POST /api/dialog-messages without dialog_id and with attributes.users missing, empty, containing only null/blank ids, or containing only the sender's own id.

Common situations: Frontend not collecting recipients before send; user attempts to message only themselves; stale UI state after recipients were removed.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at extensions/messages/src/Api/Resource/DialogMessageResource.php:239

    /**
     * @inheritDoc
     */
    public function creating(object $model, OriginalContext $context): ?object
    {
        $model->user_id = $context->getActor()->id;
        $data = $context->body()['data'] ?? [];

        $this->events->dispatch(
            new DialogMessage\Event\Creating($model, $data)
        );

        if (! $model->dialog_id) {
            $context->getActor()->assertCan('sendAnyMessage');

            $users = array_filter(Arr::pluck($data['attributes']['users'] ?? [], 'id'), fn (mixed $id) => $id && $id != $model->user_id);

            if (empty($users)) {
                throw new ValidationException([
                    'users' => str_replace(':attribute', 'users', $this->translator->trans('validation.required')),
                ]);
            }

            $dialog = Dialog::for($model, $users);

            $model->dialog()->associate($dialog);

            $users[] = $model->user_id;

            $dialog->users()->syncWithPivotValues(array_unique($users), [
                'joined_at' => Carbon::now(),
            ]);
        }

        return parent::creating($model, $context);
    }

View on GitHub (pinned to 4b939f6853)