java-native-access/jna · error · IllegalStateException
Type not supported
Error message
Type not supported: <vartype>
What it means
OaIdlUtil.toPrimitiveArray allocates the target primitive array with a switch over the requested VAREnum varType; VT_UNKNOWN, VT_DISPATCH, VT_CY, VT_DECIMAL, VT_RECORD and unknown types hit `default` and throw IllegalStateException 'Type not supported'.
Solutions
- Only call toPrimitiveArray for supported varTypes (numeric, boolean, BSTR etc.) and special-case unsupported ones
- Read VT_DECIMAL/VT_CY/VT_UNKNOWN elements manually via SAFEARRAY.getElement and Variant wrappers
- Convert the SAFEARRAY server-side to a supported element type
- Extend the switch in a fork to add the missing type
Example fix
// before
Object[] r = OaIdlUtil.toPrimitiveArray(sa, VAREnum.VT_DECIMAL);
// after
if (sa.getVarType().intValue() == VAREnum.VT_DECIMAL) {
List<DECIMAL> r = readDecimalsManually(sa);
} else {
Object[] r = OaIdlUtil.toPrimitiveArray(sa);
} Defensive patterns
Strategy: type-guard
Validate before calling
int vt = varType; boolean supported = !(vt==VAREnum.VT_UNKNOWN||vt==VAREnum.VT_DISPATCH||vt==VAREnum.VT_CY||vt==VAREnum.VT_DECIMAL||vt==VAREnum.VT_RECORD);
Type guard
boolean toPrimitiveSupported(int vartype) {
return !(vartype == VAREnum.VT_UNKNOWN || vartype == VAREnum.VT_DISPATCH
|| vartype == VAREnum.VT_CY || vartype == VAREnum.VT_DECIMAL
|| vartype == VAREnum.VT_RECORD);
} Try / catch
try {
return OaIdlUtil.toPrimitiveArray(sa);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Type not supported")) return readManually(sa);
throw e;
} Prevention
- Whitelist supported vartypes before calling OaIdlUtil
- Write custom readers for VT_CY/VT_DECIMAL/VT_UNKNOWN arrays
- Keep COM return types stable and documented
- Add unit tests covering each vartype your interop produces
When it happens
Trigger: Calling toPrimitiveArray with varType set to VT_UNKNOWN, VT_DISPATCH, VT_CY, VT_DECIMAL, VT_RECORD, or any value with no case in the switch.
Common situations: Converting arrays of COM interface pointers or currency/decimal values; assuming the utility handles all VAREnum types; a COM server changed its return type after an upgrade.
Related errors
- Can't parse array content - type not supported
- Supplied Array has no dimensions.
- advise: Interface must define a value for either iid via…
- advise: Interface must define a value for either iid via…
- Class type <paramTypes[i].getName()> not mapped to…
AI-assisted analysis of java-native-access/jna@d036ad9781 (2026-09-12).
Data as JSON: /api/errors/4bf5de31fd717a01.
Report an issue: GitHub.
Appendix: source
Thrown at contrib/platform/src/com/sun/jna/platform/win32/OaIdlUtil.java:168
break;
case VT_R8:
case VT_DATE:
sourceArray = dataPointer.getDoubleArray(0, elementCount);
break;
case VT_BSTR:
sourceArray = dataPointer.getPointerArray(0, elementCount);
break;
case VT_VARIANT:
VARIANT variant = new VARIANT(dataPointer);
sourceArray = variant.toArray(elementCount);
break;
case VT_UNKNOWN:
case VT_DISPATCH:
case VT_CY:
case VT_DECIMAL:
case VT_RECORD:
default:
throw new IllegalStateException("Type not supported: " + varType);
}
Object targetArray = Array.newInstance(Object.class, elements);
toPrimitiveArray(sourceArray, targetArray, elements, cumElements, varType, new int[0]);
return targetArray;
} finally {
sa.unaccessData();
if (destruct) {
sa.destroy();
}
}
}
private static void toPrimitiveArray(Object dataArray, Object targetArray, int[] elements, int[] cumElements, int varType, int[] currentIdx) {
int dimIdx = currentIdx.length;
int[] subIdx = new int[currentIdx.length + 1];
System.arraycopy(currentIdx, 0, subIdx, 0, dimIdx);
for (int i = 0; i < elements[dimIdx]; i++) {View on GitHub (pinned to d036ad9781)