{"record":{"id":"942983cc54a8dcf3","repo":"BoundaryML/baml","slug":"internal-error-attempted-to-register-unknown-function-s","errorCode":null,"errorMessage":"internal error: attempted to register unknown function '%s'","messagePattern":"internal error: attempted to register unknown function '(.+?)'","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/language_client_go/baml_go/lib_common.go","lineNumber":246,"sourceCode":"\t\tC.SetRegisterCallbacksFn(fnPtr)\n\tcase \"call_function_from_c\":\n\t\tC.SetCallFunctionFromCFn(fnPtr)\n\tcase \"call_function_stream_from_c\":\n\t\tC.SetCallFunctionStreamFromCFn(fnPtr)\n\tcase \"call_function_parse_from_c\":\n\t\tC.SetCallFunctionParseFromCFn(fnPtr)\n\tcase \"build_request_from_c\":\n\t\tC.SetBuildRequestFromCFn(fnPtr)\n\tcase \"cancel_function_call\":\n\t\tC.SetCancelFunctionCallFn(fnPtr)\n\tcase \"call_object_constructor\":\n\t\tC.SetCallObjectConstructorFn(fnPtr)\n\tcase \"call_object_method\":\n\t\tC.SetCallObjectMethodFunctionFn(fnPtr)\n\tcase \"free_buffer\":\n\t\tC.SetFreeBufferFn(fnPtr)\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"internal error: attempted to register unknown function '%s'\", fnName))\n\t}\n\treturn nil\n}\n\nfunc findOrDownloadLibrary() error {\n\tif bamlSharedLibraryPath != \"\" {\n\t\t_, err := os.Stat(bamlSharedLibraryPath)\n\t\tif err == nil {\n\t\t\tlogger.Debug(\"Using BAML library path set via SetSharedLibraryPath()\", \"path\", bamlSharedLibraryPath)\n\t\t\treturn nil\n\t\t}\n\t\terr = fmt.Errorf(\"%w: path explicitly set via SetSharedLibraryPath() %s is invalid: %w\", ErrLoadLibrary, bamlSharedLibraryPath, err)\n\t\treturn err\n\t}\n\n\tenvPath := os.Getenv(bamlLibraryPathEnv)\n\tif envPath != \"\" {\n\t\t_, err := os.Stat(envPath)","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_client_go/baml_go/lib_common.go#L228-L264","documentation":"registerFn() maps each known FFI symbol name to a C setter function via a switch; any name outside the fixed list of 13 expected functions hits the default branch and panics with this internal-error message (engine/language_client_go/baml_go/lib_common.go:245-247). This is an internal invariant violation: callers inside this package only ever pass hardcoded known names, so it should be unreachable in released code.","triggerScenarios":"Only reachable if the package source is modified to call registerFn with a function name that has no case in the switch (e.g. a developer adds l.registerFn(\"new_symbol\") in registerFunctions without adding a corresponding case and C setter). Not triggerable from public API.","commonSituations":"A contributor adds a new FFI entry point to registerFunctions but forgets the switch case and the matching C.Set*Fn binding; merging partial patches to the FFI surface.","solutions":["Add a case for the function name in registerFn's switch that calls the corresponding C.Set*Fn setter with the looked-up fnPtr","Add the matching extern setter to baml_cffi_wrapper.h / the C wrapper if the symbol is new","Remove the stray l.registerFn(\"...\") call in registerFunctions if the name was added by mistake","If you hit this without modifying the library, report it as a bug to boundaryml/baml with the BAML_LOG=DEBUG output — it indicates a broken build of the package"],"exampleFix":"// before\nl.registerFn(\"invoke_runtime_cli_v2\") // no case in switch -> panic\n\n// after\n// in registerFunctions: keep l.registerFn(\"invoke_runtime_cli_v2\") only if you also add:\ncase \"invoke_runtime_cli_v2\":\n    C.SetInvokeRuntimeCliV2Fn(fnPtr)","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Not user-reachable; if hit in a fork, guard your registration changes:\nfunc() {\n    defer func() {\n        if r := recover(); r != nil {\n            log.Fatalf(\"baml registerFn bug: %v\", r) // fail fast with the unknown fn name\n        }\n    }()\n    // ... library init\n}()","preventionTips":["When adding a new FFI symbol, always add both the l.registerFn(\"name\") call AND the matching case + C.Set*Fn setter in the same change","Add a unit test that asserts every name passed to registerFn has a case in the switch (table-driven over the known names)","Keep the switch in registerFn and the list in registerFunctions mechanically in sync (single source of truth constant slice)"],"tags":["go","internal-error","panic","ffi","invariant-violation"],"backgroundTag":"internal-invariant-violation","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}