laravel/framework · error · BadMethodCallException
Call to undefined method %s::%s()
Error message
Call to undefined method %s::%s()
What it means
PendingHasThroughRelationship is a placeholder returned while defining has-one/has-many-through via the pending ->has('Relation') syntax. Its __call() magic only forwards methods starting with 'has' to has(); any other method name is undefined and throws BadMethodCallException naming the class and method.
Source
Thrown at src/Illuminate/Database/Eloquent/PendingHasThroughRelationship.php:115
return $returnedRelation;
}
/**
* Handle dynamic method calls into the model.
*
* @param string $method
* @param array $parameters
* @return mixed
*
* @throws \BadMethodCallException
*/
public function __call($method, $parameters)
{
if (Str::startsWith($method, 'has')) {
return $this->has((new Stringable($method))->after('has')->lcfirst()->toString());
}
throw new BadMethodCallException(sprintf(
'Call to undefined method %s::%s()', static::class, $method
));
}
}
View on GitHub (pinned to bd6b5437e6)
Solutions
- Resolve the relationship first by calling ->has('relationName') (or hasXxx) before chaining query methods.
- Verify the method name you intend exists; use the camelCased distant relation name after 'has' (e.g. hasPosts()).
- If you need query constraints, define them via the closure form of has(): ->has(fn ($r) => $r->where(...)).
Example fix
// before $model->posts()->throughAuthor()->latest(); // throws // after $model->throughAuthor()->hasPosts()->latest();
Defensive patterns
Strategy: type-guard
Validate before calling
if (! $pending instanceof \Illuminate\Database\Eloquent\PendingHasThroughRelationship
|| ! str_starts_with($method, 'has')) {
throw new \BadMethodCallException("Unsupported call on pending relationship: {$method}");
}
$pending->{$method}(); Type guard
function isPendingHasCall(string $method): bool {
return str_starts_with($method, 'has');
} Try / catch
try {
$pending->{$method}();
} catch (\BadMethodCallException $e) {
if (str_contains($e->getMessage(), 'Call to undefined method')) {
// resolve relation via has() first
}
throw $e;
} Prevention
- Only call has* methods on PendingHasThroughRelationship.
- Resolve the relation via has('Name') before chaining query helpers.
- Use the closure form of has() for query constraints.
When it happens
Trigger: Chaining an arbitrary method on a pending through-relationship builder that does not start with 'has', e.g. $model->throughRelation()->someMethod() where someMethod is neither 'has' nor a has-prefixed accessor.
Common situations: Misunderstanding the pending relationship API and treating it as a full Builder; typos in relationship method names; calling query helpers (where, orderBy) directly on the pending object instead of the resolved relation.
Related errors
- Collection given to whereBelongsTo method may not be empty.
- Collection given to whereAttachedTo method may not be empty.
- The provided value may not be null.
- Invalid aggregate [{$aggregate}] used within ofMany relation
- Model attribute value is an object but does not have a __toS
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/8c427cecfe196d45.json.
Report an issue: GitHub.