passbolt/passbolt_api · error · CakeException

" " is not a valid datetime for filter .

Error message

"{0}" is not a valid datetime for filter {1}.

What it means

validateFilterDateTime validates datetime filters by first ensuring the value is a string, then attempting to construct a PHP DateTime from it. This throw is raised when the value passed to a datetime filter is not a string at all (e.g. an array or nested value from the query string).

Solutions

  1. Inspect the raw query string and ensure each filter value is a single scalar string.
  2. Remove duplicate bracketed values that PHP turns into arrays (e.g. filter[]=x[]).
  3. URL-encode the datetime value properly so it stays a single string.
  4. Send an unambiguous datetime string such as '2024-01-01T00:00:00+00:00' that DateTime can parse.

Example fix

// before
GET /resources?filter[]=modified-before>2024-01-01 00:00:00[]
// after
GET /resources?filter[]=modified-before>2024-01-01T00:00:00%2B00:00
Defensive patterns

Strategy: validation

Validate before calling

if (typeof filterValue !== 'string' || Array.isArray(filterValue)) {
  throw new Error('Datetime filter value must be a single scalar string');
}

Type guard

function isString(v: unknown): v is string {
  return typeof v === 'string';
}

Prevention

When it happens

Trigger: Sending a filter value that PHP parses as a non-scalar (e.g. filter[]=modified-before>foo[] producing an array), so is_string() fails before DateTime parsing is attempted.

Common situations: Malformed query strings where the same filter key repeats or brackets in the value cause PHP to coerce the value to an array; automated clients posting JSON-ish syntax into query strings.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/731ebf29ef8e6d9c. Report an issue: GitHub.

Appendix: source

Thrown at src/Controller/Component/QueryStringComponent.php:651

                __('"{0}" is not a valid timestamp for filter {1}.', $timestamp, $filterName)
            );
        }

        return true;
    }

    /**
     * Validate a filter that is a datetime.
     *
     * @param mixed $values the value to check
     * @param string $filterName for error message display
     * @throw CakeException if the filter is not valid
     * @return bool if validate
     */
    public static function validateFilterDateTime(mixed $values, string $filterName): bool
    {
        if (!is_string($values)) {
            throw new CakeException(__('"{0}" is not a valid datetime for filter {1}.', $values, $filterName));
        }
        try {
            new DateTime($values);
        } catch (Exception $e) {
            throw new CakeException(__('"{0}" is not a valid datetime for filter {1}.', $values, $filterName));
        }

        return true;
    }

    /**
     * Validate order
     *
     * @param array|null $orders a list of order to validate like ['Groups.name ASC', 'Users.created']
     * @param array|null $allowedQueryItems whitelist
     * @return bool true if validate
     * @throws \Cake\Core\Exception\CakeException if the group name does not validate
     * @deprecated Use the ApiPaginationComponent

View on GitHub (pinned to 31c1bbc10f)