{"record":{"id":"afc05f489264792a","repo":"cube-js/cube","slug":"options-contexttoapiscopes-must-be-a-function","errorCode":null,"errorMessage":"options.contextToApiScopes must be a function","messagePattern":"options\\.contextToApiScopes must be a function","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cubejs-backend-native/js/index.ts","lineNumber":388,"sourceCode":"export const resetLogger = (logLevel: LogLevel): void => {\n  const native = loadNative();\n  native.resetLogger({ logLevel });\n};\n\nexport const isFallbackBuild = (): boolean => {\n  const native = loadNative();\n  return native.isFallbackBuild();\n};\n\nexport type SqlInterfaceInstance = { __typename: 'sqlinterfaceinstance' };\n\nexport const registerInterface = async (options: SQLInterfaceOptions): Promise<SqlInterfaceInstance> => {\n  if (typeof options !== 'object' && options == null) {\n    throw new Error('Argument options must be an object');\n  }\n\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","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-backend-native/js/index.ts#L370-L406","documentation":"registerInterface requires contextToApiScopes to be a function that maps the security context to API scopes for the native SQL interface. If the property is missing or not a function, the interface cannot enforce API scoping, so it throws.","triggerScenarios":"Calling registerInterface() with an options object lacking a contextToApiScopes function, or supplying a non-function value (object, string, undefined).","commonSituations":"Following outdated docs/examples where the callback was optional or named differently; forgetting the callback when migrating to the native SQL planner; passing config from JSON where functions can't be serialized.","solutions":["Add a contextToApiScopes function to the options, e.g. (context) => context.apiScopes.","Check spelling/casing of the property name in the options object.","Ensure the options are built in code (not deserialized from JSON) so functions survive."],"exampleFix":"// before\nawait registerInterface({ checkAuth, checkSqlAuth, meta, stream });\n\n// after\nawait registerInterface({\n  contextToApiScopes: (context) => context.apiScopes ?? [],\n  checkAuth, checkSqlAuth, meta, stream\n});","handlingStrategy":"validation","validationCode":"if (typeof options.contextToApiScopes !== 'function') {\n  throw new Error('options.contextToApiScopes must be provided as a function');\n}","typeGuard":"function hasContextToApiScopes(o) {\n  return typeof o?.contextToApiScopes === 'function';\n}","tryCatchPattern":"try {\n  await registerInterface(options);\n} catch (e) {\n  if (e.message === 'options.contextToApiScopes must be a function') {\n    console.error('Add contextToApiScopes: (context) => context.apiScopes to the options.');\n  } else throw e;\n}","preventionTips":["Keep all six required callbacks in one factory function so none are forgotten.","Do not pass options built from JSON — functions cannot survive serialization.","Type the options object in TypeScript as SQLInterfaceOptions to catch missing fields at compile time."],"tags":["validation","callback","native","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"}