octobercms/october · error · SystemException

Unable to find a usable blueprint in import/export model.

Error message

Unable to find a usable blueprint in import/export model.

What it means

Thrown by BlueprintModel's getRecordQuery() (the method that builds a query for import/export) when the resolved blueprint is neither a GlobalBlueprint nor an EntryBlueprint. The method branches on the blueprint type to return a scoped query; any other blueprint kind falls through to this SystemException, meaning the import/export model is bound to a blueprint type it cannot query.

Source

Thrown at modules/tailor/traits/BlueprintModel.php:99

    }

    /**
     * resolveBlueprintModel
     */
    protected function resolveBlueprintModel()
    {
        $blueprint = $this->getBlueprintDefinition();

        if ($blueprint instanceof GlobalBlueprint) {
            return GlobalRecord::inGlobalUuid($this->blueprint_uuid);
        }

        if ($blueprint instanceof EntryBlueprint) {
            $modelClass = $blueprint->getModelClassName();
            return $modelClass::inSectionUuid($this->blueprint_uuid);
        }

        throw new SystemException('Unable to find a usable blueprint in import/export model.');
    }
}

View on GitHub (pinned to b608633a7e)

Solutions

  1. Point the import/export model at an entry section or global blueprint UUID — these are the only queryable kinds
  2. Resolve the blueprint by handle at runtime to avoid pasting the wrong UUID
  3. If you implemented a custom blueprint class, make it extend EntryBlueprint or GlobalBlueprint, or override getRecordQuery() in your model to provide a query

Example fix

// before: blueprint resolves to a non-queryable type
$model->setBlueprintUuid($mixinOrWrongUuid);
$query = $model->getRecordQuery();  // throws

// after
$blueprint = \Tailor\Classes\BlueprintIndexer::instance()->findSectionByHandle('blog_post');
$model->setBlueprintUuid($blueprint->uuid);  // EntryBlueprint
$query = $model->getRecordQuery();
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the blueprint is a queryable kind before building the record query
$blueprint = $model->getBlueprintDefinition();
if (!$blueprint instanceof \Tailor\Classes\Blueprint\EntryBlueprint
    && !$blueprint instanceof \Tailor\Classes\Blueprint\GlobalBlueprint) {
    throw new InvalidArgumentException('Import/export requires an entry or global blueprint');
}

Type guard

function isQueryableBlueprint(\Tailor\Classes\Blueprint $blueprint): bool
{
    return $blueprint instanceof \Tailor\Classes\Blueprint\EntryBlueprint
        || $blueprint instanceof \Tailor\Classes\Blueprint\GlobalBlueprint;
}

Prevention

When it happens

Trigger: Binding an import/export model to a blueprint UUID that resolves to a non-entry, non-global blueprint (e.g. a mixin or repeater-related blueprint); a misconfigured blueprint_uuid that happens to collide with another blueprint type's UUID; custom blueprint classes that do not extend EntryBlueprint or GlobalBlueprint.

Common situations: Custom blueprint types introduced by plugins being attached to import/export models; copy-paste of import configurations between blueprint kinds; UUID mix-ups where an importer points at the wrong blueprint record.

Related errors


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