DenverCoder1/github-readme-streak-stats · error · InvalidArgumentException

400

400

Error message

Invalid timezone.

What it means

getCurrentDate() resolves the current date (Y-m-d) in a caller-supplied timezone. The timezone string is passed straight to PHP's DateTimeZone constructor; when it is not a recognized timezone identifier, the constructor throws and the library re-throws it as an InvalidArgumentException with HTTP-style code 400. This lets callers distinguish bad user input (e.g. an invalid tz query parameter) from internal failures.

Solutions

  1. Validate the timezone against DateTimeZone::listIdentifiers() (or @timezone_identification_list) before calling getCurrentDate().
  2. Use full IANA identifiers like 'America/New_York' instead of abbreviations or Windows timezone names.
  3. Convert Windows timezone names with intl's timezone translation if the input originates from a Windows/ .NET system.
  4. If the parameter is optional, pass an empty string to fall back to date_default_timezone_get() rather than a placeholder value.

Example fix

// before
$date = getCurrentDate($_GET['tz'] ?? 'America/New York');
// after
$tz = $_GET['tz'] ?? '';
if ($tz !== '' && !in_array($tz, DateTimeZone::listIdentifiers(), true)) {
    $tz = '';
}
$date = getCurrentDate($tz);
Defensive patterns

Strategy: validation

Validate before calling

function isValidTimezone(string $tz): bool {
    return $tz === '' || in_array($tz, DateTimeZone::listIdentifiers(), true);
}
if (!isValidTimezone($timezone)) {
    throw new InvalidArgumentException('Unsupported timezone: ' . $timezone);
}

Type guard

function isKnownTimezone(mixed $tz): bool {
    return is_string($tz) && in_array($tz, DateTimeZone::listIdentifiers(), true);
}

Try / catch

try {
    $date = getCurrentDate($timezone);
} catch (InvalidArgumentException $e) {
    if ($e->getCode() === 400) {
        http_response_code(400);
        echo json_encode(['error' => 'Invalid timezone supplied']);
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: Calling getCurrentDate() (directly or via stats endpoints that accept a timezone parameter) with a string that is not a valid IANA timezone identifier or UTC offset, e.g. 'America/New York', 'EST' where abbreviation support is unavailable, an empty-but-whitespace string that bypasses the '' fallback, or a typo like 'Europe/Londonn'.

Common situations: Passing user-supplied timezone query parameters straight through without validation; legacy timezone abbreviations ('PST', 'CET') that DateTimeZone rejects as identifiers; config files carrying hand-edited timezone values; locale migration where an old app stored Windows timezone names ('Pacific Standard Time') instead of IANA names ('America/Los_Angeles').

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of DenverCoder1/github-readme-streak-stats@70dd50f921 (2026-09-15). Data as JSON: /api/errors/c5da8a61f0a7ef19. Report an issue: GitHub.

Appendix: source

Thrown at src/stats.php:296

            }
        }
    }
    return $contributions;
}

/**
 * Get the current date for a requested timezone.
 *
 * @param string $timezone Timezone identifier, or empty for the server default
 * @param DateTimeImmutable|null $now Current time override for tests
 * @return string Current date in Y-m-d format
 */
function getCurrentDate(string $timezone = "", ?DateTimeImmutable $now = null): string
{
    try {
        $dateTimezone = new DateTimeZone($timezone ?: date_default_timezone_get());
    } catch (Exception) {
        throw new InvalidArgumentException("Invalid timezone.", 400);
    }

    $now = $now ?: new DateTimeImmutable("now");
    return $now->setTimezone($dateTimezone)->format("Y-m-d");
}

/**
 * Normalize names of days of the week (eg. ["Sunday", " mon", "TUE"] -> ["Sun", "Mon", "Tue"])
 *
 * @param array<string> $days List of days of the week
 * @return array<string> List of normalized days of the week
 */
function normalizeDays(array $days): array
{
    return array_filter(
        array_map(function ($dayOfWeek) {
            // trim whitespace, capitalize first letter only, return first 3 characters
            $dayOfWeek = substr(ucfirst(strtolower(trim($dayOfWeek))), 0, 3);

View on GitHub (pinned to 70dd50f921)