laravel/framework · error · BadMethodCallException

Call to undefined method

Error message

Call to undefined method %s::%s()

What it means

PendingHasThroughRelationship is the intermediate object returned by the has?Through style 'through()' helper. Its __call magic only forwards methods starting with 'has' (e.g. hasPosts) to has(); any other method call is treated as undefined and throws BadMethodCallException. This surfaces typos and wrong chaining in has-one/has-many-through definitions.

Solutions

  1. Use the has() method (or a has-prefixed dynamic method) on the pending object: $this->through($relation)->has('comments').
  2. Verify the distant relationship callback you intend to call actually maps to a 'has' method.
  3. Re-read the PendingHasThroughRelationship API to confirm the only dynamic surface is has*.

Example fix

// before
return $this->through($local)->comments(); // throws

// after
return $this->through($local)->has('comments');
// or via the dynamic 'has' prefix
return $this->through($local)->hasComments();
Defensive patterns

Strategy: validation

Validate before calling

// Only methods beginning with 'has' are valid on a PendingHasThroughRelationship
if (! str_starts_with($method, 'has')) {
    throw new \BadMethodCallException("Only has* methods are valid on PendingHasThroughRelationship, got: {$method}");
}
return $this->through($local)->{$method}(...$args);

Type guard

function isValidHasThroughCall(string $method): bool {
    return str_starts_with($method, 'has');
}

Prevention

When it happens

Trigger: Writing return $this->through($relation)->someOtherMethod(...) where someOtherMethod does not start with 'has', or chaining a non-has method onto the result of through().

Common situations: Misremembering the fluent API for has-through; copy-paste from a normal relation definition; IDE autocomplete suggesting a wrong method; typo like 'thas' instead of 'has'.

Related errors


AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11). Data as JSON: /api/errors/8c427cecfe196d45. Report an issue: GitHub.

Appendix: 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 e0f6eb3518)