phalcon/cphalcon · error · Phalcon\Db\Exceptions\InvalidBindParameter
Invalid bind parameter (1)
Error message
Invalid bind parameter (1)
What it means
executePrepared(statement, placeholders, dataTypes) iterates the placeholders array by key; integer keys are treated as positional parameters (key + 1) and string keys as named parameters. Any key of another type throws InvalidBindParameter ('Invalid bind parameter (1)'). In pure PHP, array keys are always int or string, so this surfaces through non-userland placeholders — e.g. structures produced by json_decode() with unexpected keys, generators collapsed wrongly, or direct calls from other extension/Zephir code.
Source
Thrown at phalcon/Db/Adapter/Pdo/AbstractPdo.zep:514
* "inv_title" => "Test Invoice",
* ],
* [
* "inv_title" => Column::BIND_PARAM_STR,
* ]
* );
*```
*/
public function executePrepared(<\PDOStatement> statement, array placeholders, array dataTypes = []) -> <\PDOStatement>
{
var wildcard, value, type, castValue, parameter, position, itemValue;
for wildcard, value in placeholders {
if typeof wildcard == "integer" {
let parameter = wildcard + 1;
} elseif typeof wildcard == "string" {
let parameter = wildcard;
} else {
throw new InvalidBindParameter();
}
if fetch type, dataTypes[wildcard] {
/**
* The bind type needs to be string because the precision
* is lost if it is casted as a double
*/
if type == Column::BIND_PARAM_DECIMAL {
let castValue = (string) value,
type = Column::BIND_SKIP;
} else {
if Settings::get("db.force_casting") {
if typeof value != "array" {
switch type {
case Column::BIND_PARAM_INT:
let castValue = intval(value, 10);
break;View on GitHub (pinned to b7419de9cd)
Solutions
- Pass placeholders as a positional list [value, value, ...] built with array_values(), or an assoc [name => value] map with string keys
- Normalize any incoming bind structure before calling: cast keys, re-index lists
- Prefer the public query()/execute() APIs which run the same pipeline with validated input
Example fix
// before
$stmt = $connection->prepare('SELECT * FROM users WHERE id = ?');
$connection->executePrepared($stmt, $maybeMalformedBindArray, []);
// after
$stmt = $connection->prepare('SELECT * FROM users WHERE id = ?');
$connection->executePrepared($stmt, array_values($maybeMalformedBindArray), []); Defensive patterns
Strategy: type-guard
Type guard
/** Ensure every placeholder key is int (positional) or string (named). */
function normalizeBindKeys(array $placeholders): array
{
$out = [];
foreach ($placeholders as $k => $v) {
if (is_int($k) || is_string($k)) {
$out[$k] = $v;
} else {
throw new InvalidArgumentException('Invalid bind key type: ' . gettype($k));
}
}
return $out;
}
$connection->executePrepared($stmt, normalizeBindKeys($placeholders), $dataTypes); Prevention
- Prefer query()/execute() over calling the low-level public executePrepared() directly
- Re-index positional bind arrays with array_values() before passing
- Reject bind structures from external sources (decoded JSON, object casts) unless keys are verified int/string
When it happens
Trigger: Calling executePrepared() directly (it is public) with a malformed placeholders array whose keys are not plain integers or strings; passing a data structure where values ended up as keys or where key normalization (floats, nulls) happened upstream.
Common situations: Custom query layers that build bind arrays from decoded JSON or object casts; integrating with libraries that hand over untyped maps; rare direct use of this low-level method instead of query()/execute().
Related errors
- Invalid WHERE clause conditions
- Incomplete number of bind types
- Matched parameter was not found in parameters list
- Cannot prepare statement
- The 'dialectClass' '{className}' must implement Phalcon\Db\D
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/981a23ca27429a37.
Report an issue: GitHub.