{"record":{"id":"3395a572ca3732b8","repo":"ToolJet/ToolJet","slug":"directory-does-not-exist-expandeddir","errorCode":null,"errorMessage":"Directory does not exist: ${expandedDir}","messagePattern":"Directory does not exist: (.+?)","errorType":"validation","errorClass":"GrpcOperationError","httpStatus":null,"severity":"error","filePath":"plugins/packages/grpcv2/lib/operations.ts","lineNumber":32,"sourceCode":"const expandPath = (inputPath: string): string => {\n  if (inputPath.startsWith('~/')) {\n    return path.join(os.homedir(), inputPath.slice(2));\n  } else if (inputPath === '~') {\n    return os.homedir();\n  }\n  return path.resolve(inputPath);\n};\n\nconst getDefaultProtoDirectory = (): string => {\n  return path.join(os.homedir(), 'protos');\n};\n\nexport const validateFilesystemAccess = (directory: string): string => {\n  // Expand ~ to home directory if needed\n  const expandedDir = expandPath(directory);\n\n  if (!fs.existsSync(expandedDir)) {\n    throw new GrpcOperationError(`Directory does not exist: ${expandedDir}`);\n  }\n\n  const stat = fs.statSync(expandedDir);\n  if (!stat.isDirectory()) {\n    throw new GrpcOperationError(`Path is not a directory: ${expandedDir}`);\n  }\n\n  // Basic security check - prevent path traversal\n  const resolvedPath = path.resolve(expandedDir);\n  if (!resolvedPath.startsWith(process.cwd()) && !resolvedPath.startsWith(os.homedir())) {\n    console.warn(`Directory outside project root or home directory: ${resolvedPath}`);\n  }\n\n  return expandedDir;\n};\n\nexport const buildReflectionClient = async (sourceOptions: SourceOptions, serviceName: string): Promise<GrpcClient> => {\n  try {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/ToolJet/ToolJet/blob/20602a8e101f2e59686c9afde0d1402aac2c8871/plugins/packages/grpcv2/lib/operations.ts#L14-L50","documentation":"Thrown by validateFilesystemAccess when fs.existsSync returns false for the expanded directory. It fires before any proto loading, so no proto parsing has occurred. The path is expanded (~ -> homedir) and resolved before the check, so the message shows the absolute path that was probed.","triggerScenarios":"sourceOptions.proto_files_directory points to a path that does not exist on disk; a relative path resolved against an unexpected cwd; a typo in the directory; the protos folder was deleted or never created. The default fallback is os.homedir()/protos, which rarely exists on a fresh machine.","commonSituations":"Fresh checkout where ~/protos was never created; Docker/CI containers with a different HOME or working volume; config referencing an absolute path from a different developer's machine; symlinks pointing to a removed target.","solutions":["Create the directory or point proto_files_directory to the real location: mkdir -p <dir>.","Check the expanded path shown in the message — verify leading ~ expansion and cwd resolution.","If you intended the default, ensure ~/protos exists, or set proto_files_directory explicitly."],"exampleFix":"// before\nsourceOptions.proto_files_directory = '~/proto';\n// after\nsourceOptions.proto_files_directory = '~/protos';\n// then: mkdir -p ~/protos","handlingStrategy":"validation","validationCode":"function ensureDirExists(dir: string): string {\n  const fs = require('fs');\n  const expanded = dir.startsWith('~/') ? require('path').join(require('os').homedir(), dir.slice(2)) : require('path').resolve(dir);\n  if (!fs.existsSync(expanded)) throw new Error(`Proto directory missing: ${expanded}. Create it or fix proto_files_directory.`);\n  return expanded;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Create the proto directory during project setup (mkdir -p).","Resolve proto_files_directory to an absolute path in config so cwd doesn't matter.","Check existence in a preflight step before the first gRPC call."],"tags":["filesystem","configuration","path","validation"],"backgroundTag":null,"analyzedSha":"20602a8e101f2e59686c9afde0d1402aac2c8871","analyzedAt":"2026-08-13T05:58:54.221Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}