{"record":{"id":"5ba3c6e0f522e872","repo":"denoland/deno","slug":"foreign-symbol-of-type-void-is-not-supported","errorCode":null,"errorMessage":"Foreign symbol of type 'void' is not supported","messagePattern":"Foreign symbol of type 'void' is not supported","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/ffi/00_ffi.js","lineNumber":477,"sourceCode":"  symbols = { __proto__: null };\n\n  constructor(path, symbols) {\n    ({ 0: this.#rid, 1: this.symbols } = op_ffi_load(path, symbols));\n    for (const symbol in symbols) {\n      if (!ObjectHasOwn(symbols, symbol)) {\n        continue;\n      }\n\n      // Symbol was marked as optional, and not found.\n      // In that case, we set its value to null in Rust-side.\n      if (symbols[symbol] === null) {\n        continue;\n      }\n\n      if (ReflectHas(symbols[symbol], \"type\")) {\n        const type = symbols[symbol].type;\n        if (type === \"void\") {\n          throw new TypeError(\n            \"Foreign symbol of type 'void' is not supported\",\n          );\n        }\n\n        const name = symbols[symbol].name || symbol;\n        const value = op_ffi_get_static(\n          this.#rid,\n          name,\n          type,\n          symbols[symbol].optional,\n        );\n        ObjectDefineProperty(\n          this.symbols,\n          symbol,\n          {\n            __proto__: null,\n            configurable: false,\n            enumerable: true,","sourceCodeStart":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/ffi/00_ffi.js#L459-L495","documentation":"In the Deno.dlopen symbol table, an entry carrying a `type` field requests a static value read from the loaded library (op_ffi_get_static) — i.e. an exported data symbol. 'void' denotes no value at all, so it is rejected up front with a TypeError. Function symbols use { parameters, result } instead and never take a `type` field.","triggerScenarios":"Deno.dlopen(lib, { VERSION: { name: \"VERSION\", type: \"void\" } }) — any symbol object whose type is exactly \"void\".","commonSituations":"Auto-generated binding files from C headers that include void macros or placeholder entries; misunderstanding that `type` is for exported variables; hand-writing a stub entry to 'skip' a symbol.","solutions":["Delete the symbol entry (or its type field) instead of stubbing it with void","Use the real C type of the exported datum: u32, i32, f64, pointer, etc.","For exported functions, declare { parameters: [...], result: ... } rather than { type: ... }","Use optional: true only for symbols that may be missing in the library, not as a substitute for a valid type"],"exampleFix":"// before\nconst lib = Deno.dlopen(\"./libexample.so\", {\n  VERSION: { name: \"VERSION\", type: \"void\" },\n});\n\n// after\nconst lib = Deno.dlopen(\"./libexample.so\", {\n  VERSION: { name: \"VERSION\", type: \"u32\" }, // actual C type of the exported variable\n});","handlingStrategy":"validation","validationCode":"const VALID_STATIC_TYPES = new Set([\"u8\",\"u16\",\"u32\",\"u64\",\"i8\",\"i16\",\"i32\",\"i64\",\"f32\",\"f64\",\"usize\",\"isize\",\"pointer\"]);\nfunction validateStaticSymbols(symbols) {\n  for (const [key, def] of Object.entries(symbols)) {\n    if (def && typeof def === \"object\" && \"type\" in def && !VALID_STATIC_TYPES.has(def.type)) {\n      throw new Error(`symbol '${key}' has unsupported static type '${def.type}'`);\n    }\n  }\n}\nvalidateStaticSymbols(symbols);\nconst lib = Deno.dlopen(path, symbols);","typeGuard":"const VALID_STATIC_TYPES = new Set([\"u8\",\"u16\",\"u32\",\"u64\",\"i8\",\"i16\",\"i32\",\"i64\",\"f32\",\"f64\",\"usize\",\"isize\",\"pointer\"]);\nfunction isStaticSymbolDef(def: unknown): boolean {\n  return typeof def === \"object\" && def !== null && \"type\" in def &&\n    VALID_STATIC_TYPES.has((def as { type: string }).type);\n}","tryCatchPattern":"try {\n  lib = Deno.dlopen(path, symbols);\n} catch (err) {\n  if (err instanceof TypeError && err.message === \"Foreign symbol of type 'void' is not supported\") {\n    // drop or retype the void entry (it names a data symbol with no value)\n  } else throw err;\n}","preventionTips":["Only give `type` to exported data symbols, with their real C type","Declare functions as { parameters: [...], result: ... } instead of { type }","Sanitize generated bindings before dlopen instead of feeding headers verbatim","Use optional: true for possibly-missing symbols, never 'void' as a placeholder"],"tags":["ffi","dlopen","symbols","bindings"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}