{"record":{"id":"bf1b9740eaa174d9","repo":"elastic/elasticsearch","slug":"document-is-encrypted","errorCode":null,"errorMessage":"document is encrypted","messagePattern":"document is encrypted","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"modules/ingest-attachment/src/main/java/org/elasticsearch/ingest/attachment/TikaImpl.java","lineNumber":80,"sourceCode":"    /** autodetector based on this subset */\n    private static final AutoDetectParser PARSER_INSTANCE = new AutoDetectParser(PARSERS);\n\n    /** singleton tika instance */\n    private static final Tika TIKA_INSTANCE = new Tika(PARSER_INSTANCE.getDetector(), PARSER_INSTANCE);\n\n    /**\n     * parses with tika, throwing any exception hit while parsing the document\n     */\n    static String parse(final byte content[], final Metadata metadata, final int limit) throws TikaException, IOException {\n        try {\n            return TIKA_INSTANCE.parseToString(new ByteArrayInputStream(content), metadata, limit);\n        } catch (LinkageError e) {\n            if (e.getMessage().contains(\"bouncycastle\")) {\n                /*\n                 * Elasticsearch does not ship with bouncycastle. It is only used for public-key-encrypted PDFs, which this module does\n                 * not support anyway.\n                 */\n                throw new RuntimeException(\"document is encrypted\", e);\n            }\n            throw new RuntimeException(e);\n        }\n    }\n}\n","sourceCodeStart":62,"sourceCodeEnd":86,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/ingest-attachment/src/main/java/org/elasticsearch/ingest/attachment/TikaImpl.java#L62-L86","documentation":"RuntimeException('document is encrypted') from TikaImpl#parse when the JVM hits a LinkageError whose message mentions 'bouncycastle'. Elasticsearch intentionally does not ship BouncyCastle, which Tika needs only for public-key-encrypted PDFs; rather than a confusing NoClassDefFoundError, the parser rewrites it to a clear 'document is encrypted' message. Other LinkageErrors are rethrown unwrapped.","triggerScenarios":"A PDF (or other format) that is public-key/password encrypted is fed to the attachment processor; Tika attempts decryption, triggers the missing bouncycastle provider, and throws LinkageError.","commonSituations":"Security-controlled documents; scanned-and-signed PDFs with encryption; documents exported from DMS systems with default encryption.","solutions":["Decrypt the document offline (remove encryption) before sending it to ingest — the attachment module does not support encrypted files","If password-protected, strip protection with qpdf/gpg upstream","Route encrypted documents to a separate pre-processing step that can handle decryption"],"exampleFix":"// before: encrypted PDF in field 'data' -> 'document is encrypted'\n// after (offline pre-processing)\nqpdf --decrypt input.pdf output.pdf   // then ingest output.pdf","handlingStrategy":"validation","validationCode":"// Detect encryption upstream and decrypt before ingest:\nif (isEncrypted(fileBytes)) {\n    fileBytes = decryptOffline(fileBytes); // qpdf/gpg\n}","typeGuard":null,"tryCatchPattern":"try { ingest(attachmentPipeline, doc); }\ncatch (RuntimeException e) {\n    if (\"document is encrypted\".equals(e.getMessage())) { routeToManualDecryptQueue(doc); }\n    else throw e;\n}","preventionTips":["Decrypt documents in a pre-ingest stage — the attachment module will never ship BouncyCastle","Flag encrypted files at the producer and route them out of the attachment pipeline","Document that public-key-encrypted PDFs are unsupported"],"tags":["ingest","attachment","tika","encryption","bouncycastle"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}