001/*
002 * Copyright (c) 2026 Singular
003 * SPDX-License-Identifier: MIT
004 */
005
006package ai.singlr.openai;
007
008/** Exception thrown when OpenAI API operations fail. */
009public class OpenAIException extends RuntimeException {
010
011  private final int statusCode;
012
013  public OpenAIException(String message) {
014    super(message);
015    this.statusCode = 0;
016  }
017
018  public OpenAIException(String message, Throwable cause) {
019    super(message, cause);
020    this.statusCode = 0;
021  }
022
023  public OpenAIException(String message, int statusCode) {
024    super(message);
025    this.statusCode = statusCode;
026  }
027
028  public OpenAIException(String message, int statusCode, Throwable cause) {
029    super(message, cause);
030    this.statusCode = statusCode;
031  }
032
033  public int statusCode() {
034    return statusCode;
035  }
036
037  public boolean isClientError() {
038    return statusCode >= 400 && statusCode < 500;
039  }
040
041  public boolean isServerError() {
042    return statusCode >= 500;
043  }
044
045  /**
046   * Whether this error is retryable. Network errors (status 0), request timeouts (408), rate limits
047   * (429), and server errors (5xx) are considered retryable.
048   */
049  public boolean isRetryable() {
050    return statusCode == 0 || statusCode == 408 || statusCode == 429 || statusCode >= 500;
051  }
052}