{"record":{"id":"0da839cd7ffae17e","repo":"wailsapp/wails","slug":"unknown-type","errorCode":null,"errorMessage":"unknown type","messagePattern":"unknown type","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/pkg/w32/utils.go","lineNumber":198,"sourceCode":"\t\t\t\tvargs[n] = VARIANT{VT_R4 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float32))))}\n\t\t\tcase float64:\n\t\t\t\tvargs[n] = VARIANT{VT_R8, 0, 0, 0, int64(v.(float64))}\n\t\t\tcase *float64:\n\t\t\t\tvargs[n] = VARIANT{VT_R8 | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*float64))))}\n\t\t\tcase string:\n\t\t\t\tvargs[n] = VARIANT{VT_BSTR, 0, 0, 0, int64(uintptr(unsafe.Pointer(SysAllocString(v.(string)))))}\n\t\t\tcase *string:\n\t\t\t\tvargs[n] = VARIANT{VT_BSTR | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*string))))}\n\t\t\tcase *IDispatch:\n\t\t\t\tvargs[n] = VARIANT{VT_DISPATCH, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*IDispatch))))}\n\t\t\tcase **IDispatch:\n\t\t\t\tvargs[n] = VARIANT{VT_DISPATCH | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(**IDispatch))))}\n\t\t\tcase nil:\n\t\t\t\tvargs[n] = VARIANT{VT_NULL, 0, 0, 0, 0}\n\t\t\tcase *VARIANT:\n\t\t\t\tvargs[n] = VARIANT{VT_VARIANT | VT_BYREF, 0, 0, 0, int64(uintptr(unsafe.Pointer(v.(*VARIANT))))}\n\t\t\tdefault:\n\t\t\t\tpanic(\"unknown type\")\n\t\t\t}\n\t\t}\n\t\tdispparams.Rgvarg = uintptr(unsafe.Pointer(&vargs[0]))\n\t\tdispparams.CArgs = uint32(len(params))\n\t}\n\n\tvar ret VARIANT\n\tvar excepInfo EXCEPINFO\n\tVariantInit(&ret)\n\thr, _, _ := syscall.SyscallN(disp.lpVtbl.pInvoke,\n\t\tuintptr(unsafe.Pointer(disp)),\n\t\tuintptr(dispid),\n\t\tuintptr(unsafe.Pointer(IID_NULL)),\n\t\tuintptr(GetUserDefaultLCID()),\n\t\tuintptr(dispatch),\n\t\tuintptr(unsafe.Pointer(&dispparams)),\n\t\tuintptr(unsafe.Pointer(&ret)),\n\t\tuintptr(unsafe.Pointer(&excepInfo)),","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/wailsapp/wails/blob/0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3/v3/pkg/w32/utils.go#L180-L216","documentation":"ComInvoke converts variadic params into VARIANTs with a type switch covering int/int32, uint/uint32, int64, uint64, float32/64 (and pointers to each), string, *string, *IDispatch, **IDispatch, nil, and *VARIANT; anything else hits the default case and panics with 'unknown type'. It is a Marshaling limitation of this minimal wrapper, not a COM failure.","triggerScenarios":"Passing bool, int8/uint8, int16/uint16 (non-pointer), []byte, time.Time, structs, or any custom type as a parameter to w32.ComInvoke/ComPutProperty; passing a nil-valued interface with a concrete non-nil type.","commonSituations":"Automating COM APIs whose documented parameters are booleans (VT_BOOL) — the wrapper has no bool case, so even correct-looking code panics; passing Go strings wrapped in custom string types; sending enums represented as custom int types.","solutions":["Convert bools before the call — e.g. pass int32(-1)/int32(0) for VARIANT_TRUE/FALSE, or add a bool case mapping to VT_BOOL in the wrapper","Narrow custom typed ints/floats to the built-in types (int32(weekDay), float64(ratio)) before calling","For complex values, build a *w32.VARIANT yourself and pass that (VT_VARIANT|VT_BYREF is supported)","Extend the switch upstream with the missing cases and contribute the patch"],"exampleFix":"// before\nw32.ComInvoke(disp, dispid, w32.DISPATCH_METHOD, true) // bool -> panic\n\n// after\nvariantTrue := int32(-1) // VARIANT_TRUE\nw32.ComInvoke(disp, dispid, w32.DISPATCH_METHOD, variantTrue)","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isSupportedVariantParam(v any) bool {\n    switch v.(type) {\n    case int, int32, uint, uint32, int64, uint64,\n        float32, float64, string, *string,\n        *w32.IDispatch, **w32.IDispatch, *w32.VARIANT, nil:\n        return true\n    case int8, uint8, int16, uint16, bool, []byte, time.Time:\n        return false\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Convert bools to int32(-1)/int32(0) and narrow custom numeric types before ComInvoke","Pre-convert complex values into a *w32.VARIANT yourself","Add a unit test that runs isSupportedVariantParam over every param you pass"],"tags":["windows","com","variant","type-conversion","panic"],"backgroundTag":null,"analyzedSha":"0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3","analyzedAt":"2026-08-15T14:17:36.034Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}