octobercms/october · error · SystemException
Blueprint [get_class($blueprint)] does not use a database ta
Error message
Blueprint [get_class($blueprint)] does not use a database table.
What it means
SchemaBuilder::initBlueprint() prepares a content table for a blueprint, starting from $blueprint->getContentTableName(). When that method returns an empty value (blueprint kinds that store no content of their own, e.g. mixins), the builder has no table to migrate and throws a SystemException.
Source
Thrown at modules/tailor/classes/SchemaBuilder.php:134
public static function migrateBlueprint(Blueprint $blueprint, Fieldset $fieldset)
{
$builder = new self;
$builder->initBlueprint($blueprint, $fieldset);
return $builder->migrate();
}
/**
* initBlueprint
*/
public function initBlueprint(Blueprint $blueprint, Fieldset $fieldset)
{
$this->fieldset = $fieldset;
$this->blueprint = $blueprint;
$this->tableName = $blueprint->getContentTableName();
$this->tableBlueprint = $this->makeDatabaseBlueprint($fieldset);
if (!$this->tableName) {
throw new SystemException('Blueprint ['.get_class($blueprint).'] does not use a database table.');
}
$this->tableExists = Schema::hasTable($this->tableName);
$this->tableColumns = $this->tableExists ? Schema::getColumnListing($this->tableName) : [];
}
/**
* migrate
*/
public function migrate()
{
$this->actionCount = 0;
$this->migrateFields();
$this->migrateJoins();
$this->migrateRepeaters();
$this->migrateTablePatches();
View on GitHub (pinned to b608633a7e)
Solutions
- Skip blueprints without a content table before building: `if (!$blueprint->getContentTableName()) continue;`
- Only schema-build content-bearing types (entry, stream, structure, single, global) and let Tailor's own refresh (`php artisan tailor:refresh`) handle the rest.
Example fix
// before
foreach ($blueprints as $blueprint) {
$builder->initBlueprint($blueprint, $fieldset);
}
// after
foreach ($blueprints as $blueprint) {
if (!$blueprint->getContentTableName()) {
continue;
}
$builder->initBlueprint($blueprint, $fieldset);
} Defensive patterns
Strategy: validation
Validate before calling
if (!$blueprint->getContentTableName()) {
continue; // mixin-style blueprint: no table to build
}
$schemaBuilder->initBlueprint($blueprint, $fieldset); Type guard
function isTableBackedBlueprint(\Tailor\Classes\Blueprint $blueprint): bool
{
return (bool) $blueprint->getContentTableName();
} Try / catch
try {
$builder->initBlueprint($blueprint, $fieldset);
} catch (\SystemException $e) {
// blueprint has no content table (e.g. mixin); skip it in custom tooling
} Prevention
- In custom scripts that iterate blueprints, filter out table-less blueprints before schema building.
- Prefer `php artisan tailor:refresh` over hand-rolled schema building; it handles all blueprint kinds correctly.
When it happens
Trigger: Passing a mixin blueprint (or any blueprint whose getContentTableName() is null) into SchemaBuilder::initBlueprint()/migrate() — typically from custom commands or scripts that iterate every blueprint from the indexer and schema-build each one indiscriminately.
Common situations: Custom migration/import tooling looping over all blueprints; new blueprint kinds introduced without content tables; code assuming every blueprint is content-bearing.
Related errors
- Unknown document type: %s
- Cannot extend an empty model.
- Missing section definition. Call EntryRecord::inSection() to
- Missing global definition. Call GlobalRecord::inGlobal() to
- Missing a blueprint definition in import/export model.
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/40fac18333d2c77f.
Report an issue: GitHub.