octobercms/october · error · SystemException

Invalid inverse field '{$this->inverse}' for source '{$this-

Error message

Invalid inverse field '{$this->inverse}' for source '{$this->source}' for '{$this->fieldName}'.

What it means

For an entries field with an `inverse:` key, Tailor looks up that handle in the source blueprint's fieldset and requires it to be another EntriesField (getSourceFieldset()->getField()). A missing field, a wrong field type (e.g. recordfinder), or a handle that resolves to nothing means the bidirectional relation cannot be wired, so a SystemException is thrown while the model is being extended.

Source

Thrown at modules/tailor/contentfields/EntriesField.php:243

                'table' => $model->getBlueprintDefinition()->getJoinTableName(),
                'name' => $this->fieldName,
                'relationClass' => CustomMultiJoinRelation::class,
                'relatedKey' => ($relatedMultisite && !$isDualMultisite) ? 'site_root_id' : 'id',
                'relatedMultisite' => $relatedMultisite
            ];
        }
    }

    /**
     * defineInverseModelRelationship for the inverse relationship. These definitions
     * do not rely on multisite via propagatable attribute. Inverse relations do not
     * replicate and should be treated as read-only.
     */
    protected function defineInverseModelRelationship($model)
    {
        $otherField = $this->getSourceFieldset()->getField($this->inverse);
        if (!$otherField || !$otherField instanceof EntriesField) {
            throw new SystemException("Invalid inverse field '{$this->inverse}' for source '{$this->source}' for '{$this->fieldName}'.");
        }

        $parentMultisite = $model->getBlueprintDefinition()->useMultisite();
        $relatedMultisite = $this->getSourceBlueprint()->useMultisite();
        $relatedModel = $this->getSourceBlueprint()->newModelInstance();

        // Dual-multisite: both parent and related use multisite
        $isDualMultisite = $parentMultisite && $relatedMultisite;

        $isSingular = $this->maxItems === 1;
        $otherIsSingular = $otherField->maxItems === 1;
        $otherIsPropagatable = $relatedMultisite && ($otherField->translatable === false || $otherField->propagatable === true);

        // In dual-multisite, use 'id' for proper site isolation; otherwise use site_root_id for sharing
        $useRelatedRootKey = $otherIsPropagatable && !$isDualMultisite;
        $useParentRootKey = $parentMultisite && !$isDualMultisite;

        if ($isSingular) {

View on GitHub (pinned to b608633a7e)

Solutions

  1. On the source blueprint, define an entries field whose handle exactly matches the `inverse:` value.
  2. If the inverse side should be a recordfinder, remove `inverse:` from the entries field — inverse pairing requires entries-to-entries here.
  3. Re-run `php artisan tailor:refresh` after the fix so relation definitions rebuild.

Example fix

# before (blog/posts.yaml)
fields:
  author_entries:
    type: entries
    source: authors
    inverse: posts_entries   # not an entries field on authors

# after (authors/author.yaml must contain)
fields:
  posts_entries:
    type: entries
    source: blog/posts
    inverse: author_entries
Defensive patterns

Strategy: validation

Validate before calling

$fieldset = \Tailor\Classes\BlueprintIndexer::instance()->findFieldset($sourceUuid);
$inverseField = $fieldset ? $fieldset->getField($inverse) : null;
if (!$inverseField instanceof \Tailor\ContentFields\EntriesField) {
    throw new InvalidArgumentException("Inverse '{$inverse}' missing or not an entries field");
}

Type guard

function isEntriesInverse(\Tailor\Classes\Fieldset $fieldset, string $inverse): bool
{
    return $fieldset->getField($inverse) instanceof \Tailor\ContentFields\EntriesField;
}

Try / catch

try {
    $field->applyModelExtensions / tailor:refresh
} catch (\SystemException $e) {
    // message names the inverse handle; fix the source blueprint's field and refresh
}

Prevention

When it happens

Trigger: `inverse: myEntriesField` is set on an entries field, but the source blueprint defines no field with that handle, defines it as a different content field type, or defines it only at a nested level that the fieldset lookup doesn't reach.

Common situations: Typos in inverse handles; renaming the inverse field on the source blueprint without updating the other side; intending to pair entries with a recordfinder inverse; source blueprint field errors preventing proper fieldset compilation.

Related errors


AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21). Data as JSON: /api/errors/962ccb2bd9b442eb. Report an issue: GitHub.