{"record":{"id":"2f4a822ff9248cb2","repo":"nocobase/nocobase","slug":"variablesprovider-variablename-is-not-found","errorCode":null,"errorMessage":"VariablesProvider: ${variableName} is not found","messagePattern":"VariablesProvider: (.+?) is not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/client/src/variables/VariablesProvider.tsx","lineNumber":145,"sourceCode":"         */\n        fieldOperator?: string | void;\n      },\n    ) => {\n      const list = variablePath.split('.');\n      const variableName = list[0];\n      const _variableToCollectionName = mergeVariableToCollectionNameWithLocalVariables(variablesStore, localVariables);\n      let current = mergeCtxWithLocalVariables(ctxRef.current, localVariables);\n      const { fieldPath, dataSource, variableOption } = getFieldPath(variableName, _variableToCollectionName);\n      let collectionName = fieldPath;\n\n      const { fieldPath: fieldPathOfVariable } = getFieldPath(variablePath, _variableToCollectionName);\n      const collectionNameOfVariable =\n        list.length === 1\n          ? variableOption?.collectionName\n          : getCollectionJoinField(fieldPathOfVariable, dataSource)?.target;\n\n      if (!(variableName in current)) {\n        throw new Error(`VariablesProvider: ${variableName} is not found`);\n      }\n\n      for (let index = 0; index < list.length; index++) {\n        if (current == null) {\n          return {\n            value: current === undefined ? variableOption?.defaultValue : current,\n            dataSource,\n            collectionName: collectionNameOfVariable,\n          };\n        }\n\n        if (_.isFunction(current)) {\n          break;\n        }\n\n        const key = list[index];\n        const currentVariablePath = list.slice(0, index + 1).join('.');\n        const { fieldPath } = getFieldPath(currentVariablePath, _variableToCollectionName);","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/nocobase/nocobase/blob/fa42722fefe44265490dff2c27d79e2882bce4fa/packages/core/client/src/variables/VariablesProvider.tsx#L127-L163","documentation":"VariablesProvider's getResult resolves a variable path like 'currentUser.nickname' by splitting on '.' and requiring the root variable name to exist as a key in the current variables context. If the top-level variable is absent from the context (not registered yet or never provided), resolution aborts with this error naming the missing variable.","triggerScenarios":"Rendering a component whose default value / settings reference `$variablesName.field` while `variablesName` is not registered in the VariablesProvider context — e.g. the variable provider that supplies it hasn't mounted, the variable name was renamed, or the path's root doesn't match any registered variable/local variable.","commonSituations":"Using a variable in a form field default value before the upstream block providing it is loaded; typos or renames in variable names; variables set via setCtx after children already attempted resolution; deleting a collection/field that previously fed a variable.","solutions":["Ensure the provider supplying that variable (e.g. the source record block's VariablesProvider) is mounted and initialized before dependents resolve it.","Check the variable name in the path matches a registered variable exactly (case-sensitive).","Use the optional-chaining style variable expression or a default value so missing variables resolve gracefully where supported.","Wrap dependent rendering in a VariablesProvider that includes the variable, or register it via useVariablesContextAction/setCtx."],"exampleFix":"// before\nconst { result } = useVariable('$$currentUser.nickname'); // currentUser not in ctx\n// after\nif ('$currentUser' in variablesCtx) {\n  const { result } = useVariable('$$currentUser.nickname');\n} else {\n  return null; // or fallback value\n}","handlingStrategy":"try-catch","validationCode":"const rootName = variablePath.split('.')[0];\nif (!(rootName in variablesContext)) {\n  return fallbackValue; // variable not registered yet\n}","typeGuard":"function variableExists(ctx: Record<string, unknown>, path: string): boolean {\n  const root = path.split('.')[0];\n  return root in (ctx ?? {});\n}","tryCatchPattern":"try {\n  const { result } = await parseVariable(variablePath);\n  return result;\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('VariablesProvider:')) {\n    return variableOption?.defaultValue ?? null; // graceful fallback\n  }\n  throw e;\n}","preventionTips":["Wrap consumers in a VariablesProvider that registers the variable before children resolve.","Double-check variable name spelling/case in settings UIs.","Provide defaultValue on variable options so missing roots degrade gracefully.","Re-render dependents after setCtx registers new variables."],"tags":["variables","react","context-resolution"],"backgroundTag":"variable-not-found","analyzedSha":"fa42722fefe44265490dff2c27d79e2882bce4fa","analyzedAt":"2026-09-01T00:54:31.202Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}