apache/shardingsphere · error · FileIOException

30020

30020

Error message

File access failed, file is: %s

What it means

FileIOException (error code 30020) thrown by ImportMetaDataExecutor.getMetaDataFromFile when reading the file given to IMPORT METADATA fails. If the statement supplies a file path (Optional is present), FileUtils.readFileToString(file, Charset.defaultCharset()) is used; any IOException (missing/unreadable file, broken encoding) is replaced by FileIOException naming the file. This path applies only when filePath is present — the console (base64) variant reads getMetaDataValue() instead.

Source

Thrown at proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/ral/updatable/imports/ImportMetaDataExecutor.java:56

public final class ImportMetaDataExecutor implements DistSQLUpdateExecutor<ImportMetaDataStatement> {
    
    @Override
    public void executeUpdate(final ImportMetaDataStatement sqlStatement, final ContextManager contextManager) {
        String jsonMetaDataConfig = sqlStatement.getFilePath().isPresent() ? getMetaDataFromFile(sqlStatement) : getMetaDataFromConsole(sqlStatement);
        ExportedClusterInfo exportedClusterInfo = JsonUtils.fromJsonString(jsonMetaDataConfig, ExportedClusterInfo.class);
        ExportedMetaData exportedMetaData = exportedClusterInfo.getMetaData();
        new MetaDataImportExecutor(contextManager).importClusterConfigurations(exportedMetaData);
    }
    
    private String getMetaDataFromFile(final ImportMetaDataStatement sqlStatement) {
        if (!sqlStatement.getFilePath().isPresent()) {
            return "";
        }
        File file = new File(sqlStatement.getFilePath().get());
        try {
            return FileUtils.readFileToString(file, Charset.defaultCharset());
        } catch (final IOException ignore) {
            throw new FileIOException(file);
        }
    }
    
    private String getMetaDataFromConsole(final ImportMetaDataStatement sqlStatement) {
        return new String(Base64.decodeBase64(sqlStatement.getMetaDataValue()));
    }
    
    @Override
    public Class<ImportMetaDataStatement> getType() {
        return ImportMetaDataStatement.class;
    }
}

View on GitHub (pinned to e952770a21)

Solutions

  1. Ensure the metadata file exists on every proxy node that may execute the IMPORT, using an absolute path
  2. Fix read permissions for the proxy process user
  3. Alternatively use the console form (IMPORT METADATA FROM ...) with the base64 content, which bypasses file access entirely

Example fix

-- before
IMPORT METADATA FROM FILE 'metadata/export.json';

-- after
IMPORT METADATA FROM FILE '/opt/shardingsphere/metadata/export.json';
Defensive patterns

Strategy: validation

Validate before calling

if (statement.getFilePath().isPresent()) {
    File f = new File(statement.getFilePath().get());
    if (!f.isFile() || !f.canRead()) {
        throw new IllegalArgumentException("Metadata file unavailable: " + f.getAbsolutePath());
    }
}

Prevention

When it happens

Trigger: IMPORT METADATA FROM FILE '/path/metadata.json' (or equivalent) where the path is absent, unreadable, or reading fails with IOException; IMPORT METADATA without a file path does not hit this code.

Common situations: Metadata migration between clusters where the exported file was not transferred to the new proxy node; wrong working directory for a relative path; multi-node cluster where only one node has the file.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/355cfce6ba53247f. Report an issue: GitHub.