ToolJet/ToolJet · error · GrpcOperationError
Directory does not exist: ${expandedDir}
Error message
Directory does not exist: ${expandedDir} What it means
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.
Source
Thrown at plugins/packages/grpcv2/lib/operations.ts:32
const expandPath = (inputPath: string): string => {
if (inputPath.startsWith('~/')) {
return path.join(os.homedir(), inputPath.slice(2));
} else if (inputPath === '~') {
return os.homedir();
}
return path.resolve(inputPath);
};
const getDefaultProtoDirectory = (): string => {
return path.join(os.homedir(), 'protos');
};
export const validateFilesystemAccess = (directory: string): string => {
// Expand ~ to home directory if needed
const expandedDir = expandPath(directory);
if (!fs.existsSync(expandedDir)) {
throw new GrpcOperationError(`Directory does not exist: ${expandedDir}`);
}
const stat = fs.statSync(expandedDir);
if (!stat.isDirectory()) {
throw new GrpcOperationError(`Path is not a directory: ${expandedDir}`);
}
// Basic security check - prevent path traversal
const resolvedPath = path.resolve(expandedDir);
if (!resolvedPath.startsWith(process.cwd()) && !resolvedPath.startsWith(os.homedir())) {
console.warn(`Directory outside project root or home directory: ${resolvedPath}`);
}
return expandedDir;
};
export const buildReflectionClient = async (sourceOptions: SourceOptions, serviceName: string): Promise<GrpcClient> => {
try {View on GitHub (pinned to 20602a8e10)
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.
Example fix
// before sourceOptions.proto_files_directory = '~/proto'; // after sourceOptions.proto_files_directory = '~/protos'; // then: mkdir -p ~/protos
Defensive patterns
Strategy: validation
Validate before calling
function ensureDirExists(dir: string): string {
const fs = require('fs');
const expanded = dir.startsWith('~/') ? require('path').join(require('os').homedir(), dir.slice(2)) : require('path').resolve(dir);
if (!fs.existsSync(expanded)) throw new Error(`Proto directory missing: ${expanded}. Create it or fix proto_files_directory.`);
return expanded;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Path is not a directory: ${expandedDir}
- Component element not found in DOM.
- Invalid page handle: "${pageHandle}"
- MISSING_FIELDS
- INVALID_SPEC_TYPE
AI-assisted analysis of ToolJet/ToolJet@20602a8e10 (2026-08-13).
Data as JSON: /api/errors/3395a572ca3732b8.
Report an issue: GitHub.