{"record":{"id":"26953b495bdb9859","repo":"cube-js/cube","slug":"options-stream-must-be-a-function","errorCode":null,"errorMessage":"options.stream must be a function","messagePattern":"options\\.stream must be a function","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cubejs-backend-native/js/index.ts","lineNumber":404,"sourceCode":"\n  if (typeof options.contextToApiScopes !== 'function') {\n    throw new Error('options.contextToApiScopes must be a function');\n  }\n\n  if (typeof options.checkAuth !== 'function') {\n    throw new Error('options.checkAuth must be a function');\n  }\n\n  if (typeof options.checkSqlAuth !== 'function') {\n    throw new Error('options.checkSqlAuth must be a function');\n  }\n\n  if (typeof options.meta !== 'function') {\n    throw new Error('options.meta must be a function');\n  }\n\n  if (typeof options.stream !== 'function') {\n    throw new Error('options.stream must be a function');\n  }\n\n  if (typeof options.sqlApiLoad !== 'function') {\n    throw new Error('options.sqlApiLoad must be a function');\n  }\n\n  if (typeof options.sqlGenerators !== 'function') {\n    throw new Error('options.sqlGenerators must be a function');\n  }\n\n  if (typeof options.sql !== 'function') {\n    throw new Error('options.sql must be a function');\n  }\n\n  const native = loadNative();\n  return native.registerInterface({\n    ...options,\n    contextToApiScopes: wrapNativeFunctionWithChannelCallback(options.contextToApiScopes),","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-backend-native/js/index.ts#L386-L422","documentation":"registerInterface requires a stream function used to stream query results to SQL clients through the native interface. If options.stream is not a function, results cannot be streamed, so registration throws.","triggerScenarios":"Calling registerInterface() with an options object whose stream property is missing or not a function.","commonSituations":"Building the native SQL interface without a results-streaming handler; confusing the required stream callback with Node stream utilities; copy-paste omitting stream while including sqlApiLoad.","solutions":["Provide a stream function that executes the query and streams rows back, delegating to your query orchestrator.","Pass the same streaming handler used by the REST/WS API layer.","Verify the handler is referenced, not invoked, when constructing options."],"exampleFix":"// before\nawait registerInterface({ contextToApiScopes, checkAuth, checkSqlAuth, meta });\n\n// after\nawait registerInterface({\n  contextToApiScopes, checkAuth, checkSqlAuth, meta,\n  stream: async (context, query) => orchestratorApi.executeQuery(context, query),\n  sqlApiLoad\n});","handlingStrategy":"validation","validationCode":"if (typeof options.stream !== 'function') {\n  throw new Error('options.stream must be provided as a function');\n}","typeGuard":"function hasStream(o) {\n  return typeof o?.stream === 'function';\n}","tryCatchPattern":"try {\n  await registerInterface(options);\n} catch (e) {\n  if (e.message === 'options.stream must be a function') {\n    console.error('Provide stream: async (context, query) => orchestratorApi.executeQuery(context, query).');\n  } else throw e;\n}","preventionTips":["Wire the same executeQuery/streaming handler your REST/WS API uses.","Create the options object via a single factory listing all required callbacks (contextToApiScopes, checkAuth, checkSqlAuth, meta, stream, sqlApiLoad).","Add a startup assertion that validates every callback type before registerInterface runs."],"tags":["validation","callback","streaming","sql-interface"],"backgroundTag":"missing-required-callback","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}