OpenAI Java lib 4.41.0 throws OpenAIInvalidDataException in OrganizationCostsResult when parsing amount values
Nobody has claimed this yet.
- Dominant language
- Kotlin
- Stars
- 1.5k
- Forks
- 264
- Avg merge
- 9h 46m
- Merged PRs (30d)
- 96
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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with JsonField in Values.kt and the OrganizationCostsResult.Amount.value() path in UsageCostsResponse.kt, using the supplied Java example and failing values as the reproduction. Check how the numeric values are parsed, then verify that values such as 0E-6176 and the long decimal amounts can be read without OpenAIInvalidDataException.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, kotlin
- Domain
- api
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100