›
byrcsc/laravel-cartographer · 1.x
Diagnose command failures, warnings, missing models, and incorrect diagrams.
Start with the message. Every failure the command produces names its cause, and the sections below are grouped by what you are actually looking at.
Both exceptions the package defines extend RuntimeException, as does the
writer's failure. The command catches RuntimeException and
InvalidArgumentException, prints the message, and exits 1.
use Byrcsc\Cartographer\GraphAssemblyException;
use Byrcsc\Cartographer\SchemaReadException;| Exception | Thrown when |
|---|---|
SchemaReadException | The connection cannot be opened or introspected |
GraphAssemblyException | A seed is unknown, ambiguous, or has no table; depth is negative |
InvalidArgumentException | An option or config value is invalid |
RuntimeException | The output file cannot be written |
There is no single package base exception. Catch RuntimeException when driving
the PHP API yourself and you want everything the command would have
caught.
"No Eloquent models were discovered. Check the paths configured in [cartographer.paths]."
Discovery found no class that subclasses Model. Usual causes, in order:
paths points somewhere that does not exist. Run without --stdout and read
the warnings, an unmatched pattern is reported by name.composer dump-autoload after moving files."Model discovery path matched no directories: /srv/app/src/Domain/*/Models"
A warning, not a failure. The pattern matched nothing, and the run continued. Expected when a glob covers modules that are not present in this checkout; otherwise a typo or a wrong base path.
"Skipping model [App\Models\Ghost]: table [missing_ghosts] does not exist."
The class was found, but its table is not on the connection. The database is
behind the code, the model's $table is wrong, or the model belongs to a
different connection than the one being read.
php artisan migrate
php artisan cartographer:erd"Skipping model [App\Models\Report]: ..." with some other message
The model could not be instantiated, new Model threw, and the exception
message follows the colon. A constructor with required arguments will do this.
Add the model to exclude_models.
No message at all
Then the model was excluded, not skipped. Check exclude_models, and check that
the model is not abstract, abstract classes never become entities, including a
BaseModel that other models extend.
Work through these in order:
paths, in exclude_models, or with no table produces
nothing, and says nothing.--exclude-relations and
relations.exclude. Remember that morph and through are group aliases.--models, only entities within --depth
hops are kept, and edges need both ends inside the scope.relations.strict_types_only enabled, a
relation method with no Relation return type is skipped silently. This is
the one failure mode with no visible signal at all.tinker to find out.A morphTo produces no edges. Targets are resolved from the inverse side:
some discovered model has to declare a morphOne or morphMany back to this
model with the same morph name. With no inverse declared anywhere, there is
nothing to point at.
Excluding morph_many left the morph_to edges behind. Inverse relations
are read before exclusions are applied, so removing one direction does not
remove the other. Exclude morph for the whole family.
The edges are right and no column shows FK. That is a schema fact, not a bug:
markers come from real foreign key constraints, and applications that model
relationships only in Eloquent have none.
// A migration that produces FK markers.
$table->foreignId('author_id')->constrained('users');
// One that does not.
$table->unsignedBigInteger('author_id');SQLite needs foreign key support enabled on the connection for constraints to be
readable. Check foreign_key_constraints in config/database.php.
"Unable to introspect database connection [reporting]. Check the connection name, credentials, and database availability."
One message covers an unknown connection name, wrong credentials, and a database that is not running. In order:
php artisan tinker --execute="DB::connection('reporting')->getPdo();"If that fails the same way, the problem is the connection, not the package. If
it succeeds, check that cartographer.connection and --connection name the
connection you think they do, the option wins over the config key.
The original driver exception is attached to SchemaReadException as its
previous exception, so a stack trace shows the real cause.
"Seed model [Postt] was not found. Did you mean: Post, User, Comment?"
No discovered model matches by short name or fully qualified name. The suggestions are ranked by edit distance against everything discovered.
"Seed model [Order] is ambiguous. Use one of: App\Models\Order, App\Domain\Sales\Models\Order."
Two discovered models share a short class name. Pass the fully qualified name, quoted so the shell leaves the backslashes alone:
php artisan cartographer:erd --models='App\Domain\Sales\Models\Order'"Seed model [Ghost] has no available database table."
The class was discovered but never became an entity, because its table is
missing. Same fix as a skipped model: migrate, or correct the model's $table.
"Unable to write ERD to [/srv/app/docs/erd.md]."
The write is atomic, a temporary file in the destination directory, then a rename, so this covers several causes:
The previous diagram is untouched when this happens. Nothing is left half written, and the temporary file is removed.
| Message | Fix |
|---|---|
Column mode must be one of: all, keys, none. | Correct --columns or cartographer.columns.mode |
Format must be one of: markdown, mmd, svg, png. | Correct --format or cartographer.format |
Depth must be zero or a positive integer. | --depth takes 0 or more; omit it for unlimited |
[cartographer.paths] must be an array of strings. | Fix the config value |
[cartographer.exclude_models] must contain only Eloquent model class names. | An entry is not a loadable model class |
[cartographer.columns.exclude] must map Eloquent model classes to arrays of column names. | The array is keyed by table name, or a value is a bare string |
[cartographer.relations.strict_types_only] must be a boolean. | Use true, not 'true' |
[cartographer.connection] must be null or a non-empty string. | Use null for the default connection |
[cartographer.limits.max_edges] must be null or a positive integer. | Use a positive integer, or null to switch the check off |
The full list is in configuration.
"Unknown group [invoicing]. Configured groups: billing, catalog."
The name is not a key under cartographer.groups. The message lists what is
configured; with none at all it ends Configured groups: none.
"A group is already a scope, so [--group] cannot be combined with [--only], [--except], [--models] or [--depth]."
A group defines its own model set. If you want a different set, add a group or
drop --group and scope the run directly.
"A group writes to its own configured path, so [--group] cannot be combined with [--output]."
Set the group's output key in config instead. That way the check knows where
the file lives too.
"Every discovered model was excluded."
--except plus cartographer.exclude_models removed everything. The two
compose rather than replacing one another, which is the usual surprise here.
A group file keeps coming back as missing. Its models are configured but the
file was never generated. Run a bare cartographer:erd; a narrowed run
(--models, --only, --except, --output, --stdout) deliberately skips
the group files.
"No mermaid-cli binary was found in [node_modules/.bin/mmdc] or on PATH."
The svg and png formats need a renderer that this package never installs:
npm i -D @mermaid-js/mermaid-cliOr point cartographer.export.mermaid_cli at a binary you already have.
"The mermaid-cli binary configured at [...] is missing or not executable."
export.mermaid_cli is set to a path that does not resolve. Correct it, or set
it back to null to search the project and PATH. A configured path stops the
search rather than falling back, so a stale value never silently picks a
different binary.
"mermaid-cli failed to render the png diagram (exit code 1)."
The renderer's own output follows the message. This class of failure reproduces outside the package, which is the fastest way to confirm it:
npx -y @mermaid-js/mermaid-cli -i docs/erd.svg.mmd -o /tmp/erd.svgBrowser launch failures on a CI runner are the common case, and they are a Puppeteer setup problem rather than a Cartographer one.
"mermaid-cli did not finish within 300 seconds."
The diagram is large enough that rendering hangs. --columns=keys or a
group is a better answer than a longer wait.
A PNG came out on a white background. A custom theme with no background
or mainBkg variable leaves the renderer its own default canvas. Set
background. See themes and fonts.
"Unknown theme [...]" appears only sometimes. Themes are resolved only on a
run that renders an image, so a bad export.theme is silent until the first
--format=svg.
"The diagram is 63,412 characters, over the 50,000 character limit..."
"The diagram has 812 relationship edges, over the 500 edge limit..."
Warnings, not errors. The file is valid Mermaid and was written unchanged; the
exit code does not move and cartographer:check still passes. What crossed a
limit is what GitHub and GitLab will draw.
The ways out, cheapest first: --columns=keys or --columns=none, splitting
into groups, --format=svg to render it yourself, or
raising the matching key under cartographer.limits. Full detail in renderer
limits.
GitHub shows the code block as text. The fence needs to be ```mermaid,
which --format=markdown produces. If you generated with --format=mmd into a
.md file, you have a raw diagram with no fence around it.
Mermaid reports a syntax error. Table and column names that are not valid
identifiers are rewritten before rendering, so this is unusual. If it happens,
regenerate with --columns=none to find out whether the problem is in the edges
or in a column line, and open an issue with the offending name.
"Maximum text size in diagram exceeded." GitHub and GitLab refuse to draw a diagram past 50,000 characters or 500 edges. The command warns about this when it generates the file; see renderer limits for the five ways out.
The diagram is too large to read. Mermaid renders it; a human cannot. Split it into groups.
Regenerating produces a diff on an unchanged application. Check, in order:
--connection and cartographer.connection.What it is not: ordering. Every list is sorted, no timestamp or host name is written into the file, and two runs on the same inputs produce identical bytes.