MyCATApache/Mycat-Server · error · NumberFormatException

Failed to parse time string

Error message

Failed to parse time string: ${str}

What it means

JavaUtils.timeStringAs parses duration strings like "50s", "100ms". It throws NumberFormatException when the trimmed lowercase input does not match the pattern (-?[0-9]+)([a-z]+)?, meaning the string is empty, non-numeric, or otherwise malformed.

Solutions

  1. Correct the config value to match the accepted format: a signed integer with optional unit suffix (e.g. 50s, 100ms, 250us).
  2. Convert fractional values to the smallest unit first (1.5h → 90m).
  3. Trim/strip whitespace inside the string if it contains internal spaces.
  4. Provide a valid default when the config entry may be absent or empty.

Example fix

// before
long ms = JavaUtils.timeStringAsMs(conf.get("timeout")); // "1.5s"
// after
long ms = JavaUtils.timeStringAsMs("1500ms");
Defensive patterns

Strategy: validation

Validate before calling

static boolean isValidTimeString(String s) {
  return s != null && s.trim().toLowerCase().matches("-?[0-9]+([a-z]+)?");
}

Try / catch

try {
  long ms = JavaUtils.timeStringAsMs(raw);
} catch (NumberFormatException e) {
  ms = defaultMillis; // log e.getMessage() for the nested cause
}

Prevention

When it happens

Trigger: Passing a config value such as "", "50 s", "1.5s", "abc", or a value containing uppercase after trim fails to match (note lowercase() handles case) to timeStringAs/timeStringAsMs/timeStringAsSec.

Common situations: YAML/properties config with a quoted empty string, fractional durations like "1.5h", values with spaces or underscores, or environment-variable placeholders left unresolved.

Understand the failure class

Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.

Related errors


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/240cde4b477fc479. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/memory/unsafe/utils/JavaUtils.java:151

      .put("g", ByteUnit.GiB)
      .put("gb", ByteUnit.GiB)
      .put("t", ByteUnit.TiB)
      .put("tb", ByteUnit.TiB)
      .put("p", ByteUnit.PiB)
      .put("pb", ByteUnit.PiB)
      .build();

  /**
   * Convert a passed time string (e.g. 50s, 100ms, or 250us) to a time count in the given unit.
   * The unit is also considered the default if the given string does not specify a unit.
   */
  public static long timeStringAs(String str, TimeUnit unit) {
    String lower = str.toLowerCase().trim();

    try {
      Matcher m = Pattern.compile("(-?[0-9]+)([a-z]+)?").matcher(lower);
      if (!m.matches()) {
        throw new NumberFormatException("Failed to parse time string: " + str);
      }

      long val = Long.parseLong(m.group(1));
      String suffix = m.group(2);

      // Check for invalid suffixes
      if (suffix != null && !timeSuffixes.containsKey(suffix)) {
        throw new NumberFormatException("Invalid suffix: \"" + suffix + "\"");
      }

      // If suffix is valid use that, otherwise none was provided and use the default passed
      return unit.convert(val, suffix != null ? timeSuffixes.get(suffix) : unit);
    } catch (NumberFormatException e) {
      String timeError = "Time must be specified as seconds (s), " +
              "milliseconds (ms), microseconds (us), minutes (m or min), hour (h), or day (d). " +
              "E.g. 50s, 100ms, or 250us.";

      throw new NumberFormatException(timeError + "\n" + e.getMessage());

View on GitHub (pinned to 65f8d8beb7)