apache/flink · error · FlinkException

Could not stop with a detached savepoint job

Error message

Could not stop with a detached savepoint job "{}".

What it means

Thrown from NestedPrimitiveColumnReader.dictionaryDecodeValue when a dictionary-encoded nested column value's logical type root is not covered by the dictionary-decode switch (same shape as the plain-read switch: only numeric, binary/string, and timestamp cases). The message names the logical type that could not be decoded from the dictionary.

Solutions

  1. Check the message's type against dictionaryDecodeValue's switch coverage in your Flink version
  2. Re-write the data with dictionary encoding disabled for that column, which routes reads through the plain-read path (may still be unsupported — verify)
  3. Project out or restructure the unsupported nested column; or flatten/convert with Spark first
  4. Upgrade Flink — nested type coverage gaps are fixed incrementally; otherwise file a JIRA
Defensive patterns

Strategy: type-guard

Validate before calling

// Same supported-type check as the plain path, plus detect dictionary encoding from footer
for (Encoding enc : cc.getEncodings()) {
    if (enc.usesDictionary() && !nestedTypeSupported(elementType)) {
        // dictionary-encoded nested column of unsupported type will hit this error
        return Decision.CONVERT_FILE; // e.g. rewrite via Spark with dictionary disabled
    }
}

Type guard

static boolean nestedDictionarySafe(LogicalType elem, Collection<Encoding> encs) {
    return nestedTypeSupported(elem) || encs.stream().noneMatch(Encoding::usesDictionary);
}

Try / catch

try {
    reader.readAndNewVector(...);
} catch (RuntimeException e) {
    if (String.valueOf(e.getMessage()).startsWith("Unsupported type in the list")) {
        rewriteFileWithoutDictionaries(file);
    } else throw e;
}

Prevention

When it happens

Trigger: Dictionary-encoded nested (array/map element) columns of a type root absent from dictionaryDecodeValue — e.g. DECIMAL, TIME, BOOLEAN, DATE depending on physical type; same class of gap as the plain-read switch but on the dictionary path.

Common situations: Arrays of decimals or times written with dictionary encoding; files from writers that dictionary-encode aggressively; Flink versions whose nested reader switch lags the flat reader's type coverage.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/c578dfe21fe5f52a. Report an issue: GitHub.

Appendix: source

Thrown at flink-clients/src/main/java/org/apache/flink/client/cli/CliFrontend.java:848

            ClusterClient<?> clusterClient,
            JobID jobId,
            boolean advanceToEndOfEventTime,
            String targetDirectory,
            SavepointFormatType formatType,
            Duration clientTimeout)
            throws FlinkException {
        logAndSysout("Triggering stop-with-savepoint in detached mode for job " + jobId + '.');
        try {
            final String triggerId =
                    clusterClient
                            .stopWithDetachedSavepoint(
                                    jobId, advanceToEndOfEventTime, targetDirectory, formatType)
                            .get(clientTimeout.toMillis(), TimeUnit.MILLISECONDS);
            logAndSysout(
                    "Successfully trigger stop-with-savepoint in detached mode, triggerId: "
                            + triggerId);
        } catch (Exception e) {
            throw new FlinkException(
                    "Could not stop with a detached savepoint job \"" + jobId + "\".", e);
        }
    }

    /** Sends a SavepointTriggerMessage to the job manager. */
    private void triggerSavepoint(
            ClusterClient<?> clusterClient,
            JobID jobId,
            String savepointDirectory,
            SavepointFormatType formatType,
            Duration clientTimeout)
            throws FlinkException {
        logAndSysout("Triggering savepoint for job " + jobId + '.');

        CompletableFuture<String> savepointPathFuture =
                clusterClient.triggerSavepoint(jobId, savepointDirectory, formatType);

        logAndSysout("Waiting for response...");

View on GitHub (pinned to 2f3c205e92)