java-native-access/jna · error · IllegalArgumentException

Argument value 0x exceeds native capacity ( bytes) mask=0x

Error message

Argument value 0x<value> exceeds native capacity (<size> bytes) mask=0x<mask>

What it means

IntegerType.setValue throws this IllegalArgumentException when a value does not fit in the declared native width: for unsigned types the value exceeds the mask of the size in bytes, or a negative value is not representable after truncation. It protects against silently truncating values when crossing the Java/native boundary.

Solutions

  1. Mask the value before assignment: value & 0xFFFFFFFFL for a 4-byte unsigned type.
  2. Use the signed variant (e.g. SWORD instead of UWORD) if negative values are legal.
  3. Widen the type (e.g. use an 8-byte NativeLong/Long type) if values genuinely exceed capacity.

Example fix

// before
new UINT(value); // value = 0x1_FFFF_FFFFL, > 4 bytes
// after
new UINT(value & 0xFFFFFFFFL);
Defensive patterns

Strategy: validation

Validate before calling

static long maskFor(int sizeBytes) { return sizeBytes >= 8 ? ~0L : (1L << (sizeBytes * 8)) - 1; }
static long checkedUnsigned(long value, int sizeBytes) {
  long m = maskFor(sizeBytes);
  if ((value & ~m) != 0 && value >= 0) throw new IllegalArgumentException("0x" + Long.toHexString(value) + " > " + sizeBytes + " bytes");
  return value & m;
}

Try / catch

try {
  new ULONG(rawValue);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("exceeds native capacity")) {
    throw new IllegalStateException("Value 0x" + Long.toHexString(rawValue) + " does not fit; mask before constructing", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: new ULONG(-1) or new UINT32(0xFFFFFFFFL + 1) style calls; passing a long larger than the type's capacity (e.g. 2^40 into a 4-byte type); fromNative receiving a value with bits set above size*8.

Common situations: Storing unsigned constants in signed Java longs (e.g. 0xFFFFFFFF for a 4-byte unsigned type is fine, but -1 is not); arithmetic overflow before constructing the type; mixing up signed/unsigned IntegerType subclasses.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12). Data as JSON: /api/errors/13de1dda1d61e31d. Report an issue: GitHub.

Appendix: source

Thrown at src/com/sun/jna/IntegerType.java:110

                break;
            case 4:
                if (unsigned) {
                    this.value = value & 0xFFFFFFFFL;
                }
                truncated = (int) value;
                this.number = Integer.valueOf((int) value);
                break;
            case 8:
                this.number = Long.valueOf(value);
                break;
            default:
                throw new IllegalArgumentException("Unsupported size: " + size);
        }
        if (size < 8) {
            long mask = ~((1L << (size * 8)) - 1);
            if ((value < 0 && truncated != value)
                    || (value >= 0 && (mask & value) != 0)) {
                throw new IllegalArgumentException("Argument value 0x"
                        + Long.toHexString(value) + " exceeds native capacity ("
                        + size + " bytes) mask=0x" + Long.toHexString(mask));
            }
        }
    }

    @Override
    public Object toNative() {
        return number;
    }

    @Override
    public Object fromNative(Object nativeValue, FromNativeContext context) {
        // be forgiving of null values read from memory
        long value = nativeValue == null
            ? 0 : ((Number) nativeValue).longValue();
        IntegerType number = Klass.newInstance(getClass());
        number.setValue(value);

View on GitHub (pinned to d036ad9781)