java-native-access/jna · error · com.sun.jna.platform.win32.COM.COMException

createObject: Interface must define a value for either clsId

Error message

createObject: Interface must define a value for either clsId or progId via the ComInterface annotation

What it means

ObjectFactory.createObject instantiates a COM object for the given interface; it requires the interface to carry a @ComObject annotation that supplies a clsId or progId. If the annotation is missing entirely, this COMException is thrown. Without the annotation the factory has no way to know which COM class to CoCreateInstance.

Source

Thrown at contrib/platform/src/com/sun/jna/platform/win32/COM/util/ObjectFactory.java:108

    public <T> T createProxy(Class<T> comInterface, IDispatch dispatch) {
        assert COMUtils.comIsInitialized() : "COM not initialized";

        ProxyObject jop = new ProxyObject(comInterface, dispatch, this);
        Object proxy = Proxy.newProxyInstance(comInterface.getClassLoader(), new Class<?>[]{comInterface}, jop);
        T result = comInterface.cast(proxy);
        return result;
    }

    /**
     * Creates a new COM object (CoCreateInstance) for the given progId and
     * returns a ProxyObject for the given interface.
     */
    public <T> T createObject(Class<T> comInterface) {
        assert COMUtils.comIsInitialized() : "COM not initialized";

        ComObject comObectAnnotation = comInterface.getAnnotation(ComObject.class);
        if (null == comObectAnnotation) {
            throw new COMException(
                "createObject: Interface must define a value for either clsId or progId via the ComInterface annotation");
        }
        final GUID guid = this.discoverClsId(comObectAnnotation);

        final PointerByReference ptrDisp = new PointerByReference();
        WinNT.HRESULT hr = Ole32.INSTANCE.CoCreateInstance(guid, null,
            WTypes.CLSCTX_SERVER, IDispatch.IID_IDISPATCH, ptrDisp);

        COMUtils.checkRC(hr);
        Dispatch d = new Dispatch(ptrDisp.getValue());
        T t = this.createProxy(comInterface, d);
        //CoCreateInstance returns a pointer to COM object with a +1 reference count, so we must drop one
        //Note: the createProxy adds one
        int n = d.Release();
        return t;
    }

    /**

View on GitHub (pinned to d036ad9781)

Solutions

  1. Annotate the interface with @ComObject(clsId="{GUID}") or @ComObject(progId="Excel.Application")
  2. Confirm the annotation is com.sun.jna.platform.win32.COM.util.annotation.ComObject (wrong import silently fails lookup)
  3. Rebuild and verify the class file passed to createObject actually retains the annotation

Example fix

// before
public interface IApplication extends IComObject { ... }
factory.createObject(IApplication.class);
// after
@ComObject(progId = "Excel.Application")
public interface IApplication extends IComObject { ... }
factory.createObject(IApplication.class);
Defensive patterns

Strategy: validation

Validate before calling

if (iface.getAnnotation(ComObject.class) == null)
    throw new IllegalArgumentException(iface.getName() + " requires @ComObject(clsId|progId)");

Try / catch

try { T obj = factory.createObject(iface); } catch (COMException e) { if (e.getMessage().contains("clsId or progId")) { /* add annotation */ } throw e; }

Prevention

When it happens

Trigger: Calling factory.createObject(MyComInterface.class) where MyComInterface has no @ComObject annotation; interface defined against a different annotation (e.g. only @ComInterface); annotation removed in a refactor.

Common situations: Hand-writing the Java COM interface and forgetting @ComObject; migrating code that previously used raw GUIDs/IDispatch to the annotation-based util API; copy-pasting an event-callback interface (which uses @ComInterface) where a creatable class interface is needed.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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