{"record":{"id":"bc19345f3e58ec60","repo":"apache/flink","slug":"triggering-a-detached-savepoint-for-the-job-fai","errorCode":null,"errorMessage":"Triggering a detached savepoint for the job {} failed.","messagePattern":"Triggering a detached savepoint for the job (.+?) failed\\.","errorType":"exception","errorClass":"FlinkException","httpStatus":null,"severity":"critical","filePath":"flink-clients/src/main/java/org/apache/flink/client/cli/CliFrontend.java","lineNumber":900,"sourceCode":"    private void triggerDetachedSavepoint(\n            ClusterClient<?> clusterClient,\n            JobID jobId,\n            String savepointDirectory,\n            SavepointFormatType formatType,\n            Duration clientTimeout)\n            throws FlinkException {\n        logAndSysout(\"Triggering savepoint in detached mode for job \" + jobId + '.');\n\n        try {\n            final String triggerId =\n                    clusterClient\n                            .triggerDetachedSavepoint(jobId, savepointDirectory, formatType)\n                            .get(clientTimeout.toMillis(), TimeUnit.MILLISECONDS);\n\n            logAndSysout(\"Successfully trigger manual savepoint, triggerId: \" + triggerId);\n        } catch (Exception e) {\n            Throwable cause = ExceptionUtils.stripExecutionException(e);\n            throw new FlinkException(\n                    \"Triggering a detached savepoint for the job \" + jobId + \" failed.\", cause);\n        }\n    }\n\n    /** Sends a SavepointDisposalRequest to the job manager. */\n    private void disposeSavepoint(\n            ClusterClient<?> clusterClient, String savepointPath, Duration clientTimeout)\n            throws FlinkException {\n        checkNotNull(\n                savepointPath,\n                \"Missing required argument: savepoint path. \"\n                        + \"Usage: bin/flink savepoint -d <savepoint-path>\");\n\n        logAndSysout(\"Disposing savepoint '\" + savepointPath + \"'.\");\n\n        final CompletableFuture<Acknowledge> disposeFuture =\n                clusterClient.disposeSavepoint(savepointPath);\n","sourceCodeStart":882,"sourceCodeEnd":918,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-clients/src/main/java/org/apache/flink/client/cli/CliFrontend.java#L882-L918","documentation":"Thrown from NestedPrimitiveColumnReader.initDataReader when a nested column's page is dictionary-encoded but the reader has no dictionary — the dictionary page was absent or failed earlier. This is the nested-reader equivalent of the flat reader's 'dictionary was missing' error: the page metadata promises dictionary ids but there is no dictionary to resolve them against.","triggerScenarios":"initDictionaryPage ran when pageReader.readDictionaryPage() returned null (or its try block set nothing), and later pages are dictionary-encoded; malformed column chunks omitting the dictionary page; PageReader implementations that skip dictionary pages.","commonSituations":"Corrupt or non-standard files from exotic writers; row groups where dictionary overflow fallback was handled incorrectly by the writer; custom PageReaders (e.g. in iceberg/hoodie-style stacks) that mis-handle dictionary pages.","solutions":["Verify with `parquet-tools meta` that dictionary-encoded pages in that column chunk are preceded by a dictionary page","Re-obtain/regenerate the file; a dictionary-encoded page without a dictionary page is invalid Parquet","If using a custom ParquetReaderFactory/PageReader supplier, ensure readDictionaryPage() returns the chunk's dictionary page before data pages","Rewrite the file with a standard writer as a workaround"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// With parquet-mr, confirm the dictionary page exists for dictionary-encoded chunks\ntry (ParquetFileReader r = ParquetFileReader.open(conf, path)) {\n    PageReadStore rowGroup = r.readNextRowGroup();\n    for (ColumnChunkMetaData cc : rowGroup.getRowGroups().get(0).getColumns()) {\n        boolean needsDict = cc.getEncodings().stream().anyMatch(Encoding::usesDictionary);\n        // parquet-mr delivers it via ParquetFileReader; a missing dict page makes\n        // readDictionaryPage() return null — flag the file before vectorized reading\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    nestedReader.readAndNewVector(...);\n} catch (IOException e) {\n    if (String.valueOf(e.getMessage()).contains(\"dictionary was missing\")) {\n        quarantine(file); // deterministic\n    } else throw e;\n}","preventionTips":["Only read nested Parquet from writers with validated dictionary-page behavior","When implementing custom ParquetReaderFactory/PageReaders, unit-test dictionary page delivery","Quarantine malformed files at ingestion; do not let one file fail the whole source"],"tags":["parquet","nested","dictionary","data-corruption"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}