›
›
›
  1. docs
  2. ›
  3. byrcsc/laravel-cartographer
1.x
Browse documentationOpenClose

Getting started

  • Introduction
  • Installation and setup
  • Quick start

Core concepts

  • How a diagram is built
  • Model discovery
  • Relationship detection
  • Schema introspection
  • Scoping a diagram

Operations

  • Diagrams per subsystem
  • Exporting images
  • Themes and fonts
  • Renderer limits
  • Keeping the diagram current
  • Continuous integration

Reference

  • Configuration
  • Console commands
  • Diagram syntax
  • PHP API
  • Testing
  • Troubleshooting

Getting started

  • Introduction
  • Installation and setup
  • Quick start

Core concepts

  • How a diagram is built
  • Model discovery
  • Relationship detection
  • Schema introspection
  • Scoping a diagram

Operations

  • Diagrams per subsystem
  • Exporting images
  • Themes and fonts
  • Renderer limits
  • Keeping the diagram current
  • Continuous integration

Reference

  • Configuration
  • Console commands
  • Diagram syntax
  • PHP API
  • Testing
  • Troubleshooting

byrcsc/laravel-cartographer · 1.x

Troubleshooting.

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.

Catching package exceptions

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;
ExceptionThrown when
SchemaReadExceptionThe connection cannot be opened or introspected
GraphAssemblyExceptionA seed is unknown, ambiguous, or has no table; depth is negative
InvalidArgumentExceptionAn option or config value is invalid
RuntimeExceptionThe 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.

Nothing was generated

"No Eloquent models were discovered. Check the paths configured in [cartographer.paths]."

Discovery found no class that subclasses Model. Usual causes, in order:

  1. paths points somewhere that does not exist. Run without --stdout and read the warnings, an unmatched pattern is reported by name.
  2. Models live outside the configured directories. Add the directory, or a glob covering it.
  3. The autoloader cannot resolve the classes. Discovery reads class names from the file's tokens, then asks the autoloader for them. Run 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.

A model is missing from the diagram

"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.

An edge is missing

Work through these in order:

  1. Is the related model in the diagram? An edge needs both ends. A relation to a model outside paths, in exclude_models, or with no table produces nothing, and says nothing.
  2. Is the relation type excluded? Check --exclude-relations and relations.exclude. Remember that morph and through are group aliases.
  3. Is the diagram scoped? With --models, only entities within --depth hops are kept, and edges need both ends inside the scope.
  4. Is the method typed? With 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.
  5. Does the method throw? A relation method that raises is skipped. Call it in 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.

No FK markers anywhere

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.

The connection fails

"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 errors

"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.

The file cannot be written

"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 path is a directory, not a file.
  • The destination directory cannot be created, or is not writable by the user running the command.
  • The filesystem filled up mid-write.

The previous diagram is untouched when this happens. Nothing is left half written, and the temporary file is removed.

Option and config errors

MessageFix
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.

Group errors

"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.

Export errors

"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-cli

Or 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.svg

Browser 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 too big to render

"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.

The diagram will not render

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.

The diagram changed and nothing else did

Regenerating produces a diff on an unchanged application. Check, in order:

  1. A different connection. A staging database with an extra column produces a different diagram. Compare --connection and cartographer.connection.
  2. A different set of migrations. A branch with an unmerged migration applied locally shows up here.
  3. New models on disk. A generated or scaffolded model in a scanned directory becomes an entity.

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.

What to read next

  • Configuration for every key and its validation.
  • Console commands for options and exit codes.
  • Relationship detection for why an edge exists or does not.
PreviousTesting
View source

On this page

  1. Catching package exceptions
  2. Nothing was generated
  3. A model is missing from the diagram
  4. An edge is missing
  5. No FK markers anywhere
  6. The connection fails
  7. Seed model errors
  8. The file cannot be written
  9. Option and config errors
  10. Group errors
  11. Export errors
  12. The diagram is too big to render
  13. The diagram will not render
  14. The diagram changed and nothing else did
  15. What to read next