Skip to main content

CAP.PRESCAN.DYNAMIC_CALL — Unresolvable call from a migration

  • Category: safety
  • Level: 0
  • Stability: stable
  • Suites: lint

This migration makes a call whose target only exists at run time — call_user_func(...), Http::$method(...), $send(...), new $class() — or runs code from outside the file, through include, require or eval(), so the pre-scan cannot say what it runs. The other pre-scan rules match what a call reaches against catalogs of known surfaces, and a call like this matches none of them. That is not a sign that it is safe: pretend mode would run it for real, and it could send a request or a mail as easily as format a string. The migration is reported and never pretend-executed.

A call on the migration's own $this, self or static with a variable method name is not flagged. It can only reach a method of the migration, and once such a call is present the pre-scan reads every method the migration has.

Write the call out so the pre-scan can read it, move it into a step the deploy runs after the migration, or capture the migration in shadow mode against a throwaway database.

Flagged​

public function up(): void
{
// Which method runs is decided at run time, so no catalog can
// say whether it sends a request or only formats a string.
$method = config('backfill.transport');

Http::$method('https://example.test/deployed');
}

Preferred​

public function up(): void
{
Schema::table('users', fn (Blueprint $t) => $t->string('slug')->nullable());
}

// The notification is a step the deploy runs after the migration,
// where the call is written out and can be read.