Repository navigation
OpenAI Java lib 4.41.0 throws OpenAIInvalidDataException in OrganizationCostsResult when parsing amount values #769
Copy link
Copy link
Closed
Description
Environment:
- Java VM: Java JDK 8, Java JDK 21 (Azul Systems, Inc.)
- OpenAI Java: 4.41.0, 4.42.0
Description:
Parsing the amount from a OrganizationCostsResult to a value and currency throws an OpenAIInvalidDataException when amount values like 0E-6176 or 0.003627500000000000000000000000000000 are received.
Code snippet:
OrganizationCostsResult costs = result.asOrganizationCosts();
double value = costs.amount()
.flatMap(amount -> amount.value()) // <== exception on amount.value()
.orElse(0.0);
Exception thrown:
Exception in thread "main" com.openai.errors.OpenAIInvalidDataException: `value` is invalid, received 0E-6176
at com.openai.core.JsonField.getOptional$openai_java_core(Values.kt:191)
at com.openai.models.admin.organization.usage.UsageCostsResponse$Data$Result$OrganizationCostsResult$Amount.value(UsageCostsResponse.kt:6680)
at com.github.jlangch.venice.util.openai.bugs.UsageCostJsonParserBug.lambda$2(UsageCostJsonParserBug.java:72)
at java.util.Optional.flatMap(Optional.java:241)
at com.github.jlangch.venice.util.openai.bugs.UsageCostJsonParserBug.lambda$1(UsageCostJsonParserBug.java:72)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at com.github.jlangch.venice.util.openai.bugs.UsageCostJsonParserBug.lambda$0(UsageCostJsonParserBug.java:59)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at com.github.jlangch.venice.util.openai.bugs.UsageCostJsonParserBug.main(UsageCostJsonParserBug.java:55)
Some additional OpenAIInvalidDataException messages with other values that failed parsing:
`value` is invalid, received 0E-6176
`value` is invalid, received 0.003627500000000000000000000000000000
`value` is invalid, received 0.007605000000000000000000000000000000
Example code demonstrating the parser exception:
package com.github.jlangch.venice.util.openai.bugs;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;
import com.openai.models.admin.organization.usage.UsageCostsParams;
import com.openai.models.admin.organization.usage.UsageCostsResponse;
import com.openai.models.admin.organization.usage.UsageCostsResponse.Data.Result.OrganizationCostsResult;
/**
* Demonstrates the openai-java <code>OrganizationCostsResult</code> value parser bug
*
* Depends on OpenAI: com.openai:openai-java:4.41.0
*/
public class UsageCostJsonParserBug {
private UsageCostJsonParserBug() {}
public static void main(String[] args) {
final OpenAIClient client = OpenAIOkHttpClient
.builder()
.adminApiKey(System.getenv("OPENAI_ADMIN_KEY"))
.build();
final long startTime = LocalDate
.now(ZoneOffset.UTC)
.minusDays(10)
.atStartOfDay(ZoneOffset.UTC)
.toEpochSecond();
final long endTime = Instant.now().getEpochSecond();
final UsageCostsParams params = UsageCostsParams
.builder()
.startTime(startTime)
.endTime(endTime)
.bucketWidth(UsageCostsParams.BucketWidth._1D)
.addGroupBy(UsageCostsParams.GroupBy.PROJECT_ID)
.addGroupBy(UsageCostsParams.GroupBy.API_KEY_ID)
.addGroupBy(UsageCostsParams.GroupBy.LINE_ITEM)
.limit(180)
.build();
final UsageCostsResponse response = client
.admin()
.organization()
.usage()
.costs(params);
response.data().forEach(bucket -> {
final LocalDateTime bucketStart = toLocalDateTime(bucket.startTime());
final LocalDateTime bucketEnd = toLocalDateTime(bucket.endTime());
bucket.results().forEach(result -> {
if (!result.isOrganizationCosts()) {
return;
}
final OrganizationCostsResult costs = result.asOrganizationCosts();
try {
final double value;
if (true) {
// The OpenAI value Json number parser throws an exception
value = costs.amount()
.flatMap(amount -> amount.value()) // <== exception
.orElse(0.0);
}
else {
// This custom JsonField number parser works fine
value = Double.parseDouble(
costs.amount().isPresent()
? costs.amount().get()._value().asString().orElse("0.0")
: "0.0");
}
final String currency = costs.amount()
.flatMap(amount -> amount.currency())
.orElse("unknown");
final String lineItem = costs.lineItem().orElse("-");
System.out.println(String.format(
"%s – %s | %.6f %s | %s",
bucketStart,
bucketEnd,
value,
currency,
lineItem));
}
catch(Exception ex) {
/*
Exception:
com.openai.errors.OpenAIInvalidDataException: `value` is invalid, received 0E-6176
at com.openai.core.JsonField.getOptional$openai_java_core(Values.kt:191)
at com.openai.models.admin.organization.usage.UsageCostsResponse$Data$Result$OrganizationCostsResult$Amount.value(UsageCostsResponse.kt:6680)
Some exception messages:
`value` is invalid, received 0E-6176
`value` is invalid, received 0.003627500000000000000000000000000000
`value` is invalid, received 0.007605000000000000000000000000000000
Exception in thread "main" com.openai.errors.OpenAIInvalidDataException: `value` is invalid, received 0E-6176
at com.openai.core.JsonField.getOptional$openai_java_core(Values.kt:191)
at com.openai.models.admin.organization.usage.UsageCostsResponse$Data$Result$OrganizationCostsResult$Amount.value(UsageCostsResponse.kt:6680)
at com.github.jlangch.venice.util.openai.bugs.UsageCostJsonParserBug.lambda$2(UsageCostJsonParserBug.java:72)
at java.util.Optional.flatMap(Optional.java:241)
at com.github.jlangch.venice.util.openai.bugs.UsageCostJsonParserBug.lambda$1(UsageCostJsonParserBug.java:72)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at com.github.jlangch.venice.util.openai.bugs.UsageCostJsonParserBug.lambda$0(UsageCostJsonParserBug.java:59)
at java.util.ArrayList.forEach(ArrayList.java:1259)
at com.github.jlangch.venice.util.openai.bugs.UsageCostJsonParserBug.main(UsageCostJsonParserBug.java:55)
*/
System.out.println("Exception: " + ex.getMessage());
throw ex;
}
});
});
}
private static LocalDateTime toLocalDateTime(final long epochSeconds) {
return LocalDateTime.ofInstant(
Instant.ofEpochSecond(epochSeconds),
ZoneOffset.UTC);
}
}If the custom JsonField number parser in the above example is activated the cost items are fine. NoOpenAIInvalidDataExceptions:
2026-06-26T00:00 – 2026-06-27T00:00 | 0.000000 usd | gpt-5.4-2026-03-05, cached input
2026-06-26T00:00 – 2026-06-27T00:00 | 0.003210 usd | gpt-5.4-2026-03-05, input
2026-06-26T00:00 – 2026-06-27T00:00 | 0.008490 usd | gpt-5.4-2026-03-05, output
2026-06-26T00:00 – 2026-06-27T00:00 | 0.000000 usd | gpt-5-search-api-2025-10-14, cached input
2026-06-26T00:00 – 2026-06-27T00:00 | 0.059730 usd | gpt-5-search-api-2025-10-14, input
2026-06-26T00:00 – 2026-06-27T00:00 | 0.010290 usd | gpt-5-search-api-2025-10-14, output
2026-06-26T00:00 – 2026-06-27T00:00 | 0.020000 usd | web search tool calls
2026-06-27T00:00 – 2026-06-28T00:00 | 0.000000 usd | gpt-5.4-2026-03-05, cached input
2026-06-27T00:00 – 2026-06-28T00:00 | 0.002495 usd | gpt-5.4-2026-03-05, input
2026-06-27T00:00 – 2026-06-28T00:00 | 0.003525 usd | gpt-5.4-2026-03-05, output
2026-06-28T00:00 – 2026-06-29T00:00 | 0.000000 usd | gpt-5.4-2026-03-05, cached input
2026-06-28T00:00 – 2026-06-29T00:00 | 0.027858 usd | gpt-5.4-2026-03-05, input
2026-06-28T00:00 – 2026-06-29T00:00 | 0.106335 usd | gpt-5.4-2026-03-05, output
2026-06-28T00:00 – 2026-06-29T00:00 | 0.000000 usd | gpt-5.5-2026-04-23, cached input
2026-06-28T00:00 – 2026-06-29T00:00 | 0.083110 usd | gpt-5.5-2026-04-23, input
2026-06-28T00:00 – 2026-06-29T00:00 | 0.625530 usd | gpt-5.5-2026-04-23, output
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
[-]OpenAI Java lib 4.41.0 throws exception in OrganizationCostsResult when parsing values[/-][+]OpenAI Java lib 4.41.0 throws OpenAIInvalidDataException in OrganizationCostsResult when parsing amount values[/+]fix: accept quoted numeric strings in OrganizationCostsResult.Amount.…
patrickswedish commentedon Aug 1, 2026
I’m working on a focused fix for this. I reproduced the failure path on current main with a no-network regression covering both
0E-6176and long decimal numeric strings. The SDK intentionally disables global string-to-float coercion, so the fix is scoped to the organization cost amount accessor, preserving normal numeric, missing/null, raw JSON, and invalid-value behavior.PR: #834
jlangch commentedon Aug 16, 2026
Hi everyone,
It appears that OpenAI has fixed the issue on the server side and is now returning JSON floating-point values instead of strings for cost amounts, as specified by the API contract.
Could anyone from OpenAI please confirm that this issue has indeed been resolved by the OpenAI server team?
In any case, I believe this is the correct way to address the issue. If the API contract specifies a floating-point value, the server should not return a string. Modifying the client to handle strings would merely be a workaround and would not address the underlying problem.
Both pull requests #834 and #771, which attempt to address the issue on the client side, are still open. From my perspective, these changes are no longer necessary if the server-side issue has been resolved.
dpiet-oai commentedon Sep 20, 2026
Confirmed: this was resolved server-side. The Costs API response serialization was corrected so that
amount.valueis returned as a JSON number, matching the documented API contract. This is consistent with your observation that the endpoint is returning numeric values again.Closing this issue as resolved, along with #771 and #834, since the client-side string-parsing workarounds are no longer needed for this bug. No Java SDK upgrade is required for the server-side fix.
Thanks for the detailed report and follow-up! If you see string-valued amounts again, please let us know and we can reopen.