Skip to content

8.8.2: empty PHP arrays now reach the API as JSON arrays where objects are expected — request rejected with no pointer to the cause #392

Description

Summary

The v8.8.2 change ("Empty arrays and objects are no longer stripped when passed as params in the request") has a PHP-specific consequence that's easy to hit and hard to trace back to the SDK: an empty PHP array now reaches the API as a JSON array ([]) in positions where the API expects an object, and the request is rejected.

We're not asking you to revert — forwarding what the caller passed is a reasonable position. We're raising this because the failure mode is hard to diagnose, and other consumers will likely hit it as 8.8.2 propagates.

Details

PHP has no way to distinguish an empty list from an empty map — [] is the only natural empty value, and json_encode picks the array reading. Code like this is common:

$options = [];

if ($needsDdp) {
    $options['incoterm'] = 'DDP';
}

$shipment = $client->shipment->create([
    // ...
    'options' => $options,   // [] when no branch fired
]);

Before 8.8.2 the SDK stripped the empty options, so this worked. On 8.8.2 the API receives "options": [] and rejects the shipment with:

The provided options are not valid.

Nothing in that message points at the SDK, the upgrade, or the empty array — for us it surfaced only as runtime API errors on previously working code after a routine patch-level composer update.

We verified against the live API that the rejection is purely about JSON type: the same shipment with "options": {} (raw request; the SDK can't produce an empty object from PHP) returns 201 with rates, "options": [] returns 422, and omitting the key returns 201.

Suggestions

Any of these would help, roughly in order of value:

  1. Coerce empty arrays to {} for params documented as objects (options, customs_info, …). Since {} is accepted by the API, this fully restores the conditional-build pattern above — and there's currently no way to send an empty object through the SDK at all (Requestor::encodeObjects handles arrays and EasypostObjects, so a caller-supplied stdClass doesn't survive encoding either).
  2. Add a compatibility warning to the 8.8.2 changelog entry and UPGRADE guide noting that previously-stripped empty params are now sent, and that object-typed params passed as [] will be rejected by the API — so people who hit "The provided options are not valid." can find their way here by searching.
  3. Failing either, a note in the README's request-params section about the [] vs {} ambiguity.

Happy to open a PR for (1) or (2) if that's welcome.

Environment

  • easypost-php 8.8.2 (upgraded from 8.7.0)
  • PHP 8.4
  • Observed with shipment->create when options is an empty array; any object-typed param passed as [] should reproduce.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions