vitessio/vitess · error
cannot read file %v: %v
Error message
cannot read file %v: %v
What it means
When the -file flag form is used, getFileParam reads the file with os.ReadFile; if that read fails (missing file, permissions, directory instead of file), the underlying OS error is wrapped with the file path and returned.
Source
Thrown at go/vt/vtctl/vtctl.go:824
return fmt.Sprintf("%v %v %v %v %v %v %v %v", topoproto.TabletAliasString(ti.Alias), keyspace, shard, topoproto.TabletTypeLString(ti.Type), ti.Addr(), ti.MysqlAddr(), fmtMapAwkable(ti.Tags), mtst)
}
// getFileParam returns a string containing either flag is not "",
// or the content of the file named flagFile
func getFileParam(flag, flagFile, name string) (string, error) {
if flag != "" {
if flagFile != "" {
return "", fmt.Errorf("action requires only one of %v or %v-file", name, name)
}
return flag, nil
}
if flagFile == "" {
return "", fmt.Errorf("action requires one of %v or %v-file", name, name)
}
data, err := os.ReadFile(flagFile)
if err != nil {
return "", fmt.Errorf("cannot read file %v: %v", flagFile, err)
}
return string(data), nil
}
// keyspaceParamsToKeyspaces builds a list of keyspaces.
// It supports topology-based wildcards, and plain wildcards.
// For instance:
// us* // using plain matching
// * // using plain matching
func keyspaceParamsToKeyspaces(ctx context.Context, wr *wrangler.Wrangler, params []string) ([]string, error) {
result := make([]string, 0, len(params))
for _, param := range params {
if len(param) == 0 {
return nil, errors.New("empty keyspace param in list")
}
if param[0] == '/' {
// this is a topology-specific path
result = append(result, params...)View on GitHub (pinned to 01a25a7d17)
Solutions
- Verify the file exists at the exact path: check with `ls -l <path>` from the same working directory used for the command.
- Fix permissions so the vtctl process user can read the file.
- Use an absolute path in scripts and CI to avoid working-directory mismatches.
- Confirm volume mounts/configmaps actually contain the file when running in containers.
Example fix
// before ApplySchema --sql-file ./schem.sql commerce // typo, file missing // after ApplySchema --sql-file /etc/vitess/schema.sql commerce
Defensive patterns
Strategy: validation
Validate before calling
const fs = require("fs")
fs.accessSync(sqlFilePath, fs.constants.R_OK) // throws early if missing/unreadable Type guard
function fileReadable(p) {
try { require("fs").accessSync(p, require("fs").constants.R_OK); return true } catch { return false }
} Try / catch
try {
run(`vtctlclient ApplySchema --sql-file ${p} commerce`)
} catch (e) {
if (String(e).includes("cannot read file")) {
console.error(`File unreadable: ${p}. Check existence, permissions, and cwd.`)
} else throw e
} Prevention
- Use absolute paths for -file flags in scripts and CI.
- Check file existence and readability from the same user/container that runs vtctl.
- Verify volume mounts and configmaps include the schema file before deployment.
When it happens
Trigger: Running ApplySchema with `--sql-file <path>` (or analogous -file flag) where the path does not exist, is unreadable by the vtctl process user, or points to a directory.
Common situations: Relative path resolved from a different working directory in scripts/CI; file created by another user with restrictive permissions; typo in the filename; container image missing the mounted schema file.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- action requires only one of %v or %v-file
- action requires one of %v or %v-file
- the <cell> argument is required for the UpdateCellInfo comma
- the <cell> argument is required for the DeleteCellInfo comma
- GetCellInfoNames command takes no parameter
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/54fe7b3abbf6e8de.
Report an issue: GitHub.