Summary
This incident stemmed from a type‑mismatch bug in a PHP cURL integration with Google’s computeRoutes API. A developer attempted to pass a stdClass object directly into CURLOPT_POSTFIELDS, which only accepts strings, arrays, or URL‑encoded form data. The result was the runtime error: “Object of class stdClass could not be converted to string.”
Root Cause
The root cause was the use of:
json_decode(json_encode($array))which produces a stdClass object- Passing that object directly into
CURLOPT_POSTFIELDS - cURL attempting to convert the object to a string and failing
Key takeaway: CURLOPT_POSTFIELDS requires a JSON string, not a PHP object.
Why This Happens in Real Systems
This class of bug is extremely common because:
- PHP’s
json_decode()defaults to returning objects, not arrays - cURL silently accepts many types but not objects
- Developers often assume cURL will auto‑serialize complex structures
- Dynamic payload generation makes type drift easy to miss
Real-World Impact
These failures often cause:
- Silent API request failures with no useful response body
- Hard‑to‑debug production errors because the payload never reaches the API
- Inconsistent behavior when switching between static and dynamic payloads
- Misleading error messages that point to PHP internals instead of the API
Example or Code (if necessary and relevant)
Below is the correct way to send the dynamically generated payload.
$payload = json_encode($this->converToObjects());
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => 'https://routes.googleapis.com/directions/v2:computeRoutes',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-Goog-Api-Key: myPrivateKey',
'X-Goog-FieldMask: *'
],
]);
$res = curl_exec($curl);
curl_close($curl);
How Senior Engineers Fix It
Experienced engineers apply a few consistent practices:
- Always encode payloads explicitly using
json_encode() - Never pass objects into cURL unless they are strings
- Validate payloads by logging the JSON before sending
- Use associative arrays (
json_decode($json, true)) to avoid unwanted stdClass objects - Write small helpers to enforce consistent serialization
Why Juniors Miss It
This issue is easy for less experienced developers to overlook because:
- PHP’s loose typing hides type errors until runtime
json_decode()returning objects by default is unintuitive- cURL’s error message does not clearly indicate the real problem
- Static payloads work fine, so the dynamic version seems equivalent
- They assume cURL will “figure it out” and serialize automatically
Bottom line: The fix is simple—always send a JSON string, never a PHP object.