{"record":{"id":"a1327f594ff5548e","repo":"opendataloader-project/opendataloader-pdf","slug":"options-hybrid-hancom-ai-require-hybrid-hanc","errorCode":null,"errorMessage":"Options --hybrid-hancom-ai-* require --hybrid=hancom-ai (got --hybrid=%s)","messagePattern":"Options --hybrid-hancom-ai-\\* require --hybrid=hancom-ai \\(got --hybrid=(.+?)\\)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/api/cli/CLIOptions.java","lineNumber":768,"sourceCode":"        }\n        if (commandLine.hasOption(HYBRID_HANCOM_AI_CROP_OUTPUT_DIR_LONG_OPTION)) {\n            String value = commandLine.getOptionValue(HYBRID_HANCOM_AI_CROP_OUTPUT_DIR_LONG_OPTION);\n            if (value != null && !value.trim().isEmpty()) {\n                config.getHybridConfig().setCropOutputDir(value.trim());\n            }\n        }\n        if (commandLine.hasOption(TO_STDOUT_LONG_OPTION)) {\n            config.setOutputStdout(true);\n        }\n        // Keep in sync with all HYBRID_HANCOM_AI_*_LONG_OPTION constants above.\n        boolean usesHancomAiOnly =\n                commandLine.hasOption(HYBRID_HANCOM_AI_REGIONLIST_STRATEGY_LONG_OPTION) ||\n                commandLine.hasOption(HYBRID_HANCOM_AI_OCR_STRATEGY_LONG_OPTION) ||\n                commandLine.hasOption(HYBRID_HANCOM_AI_IMAGE_CACHE_LONG_OPTION) ||\n                commandLine.hasOption(HYBRID_HANCOM_AI_SAVE_CROPS_LONG_OPTION) ||\n                commandLine.hasOption(HYBRID_HANCOM_AI_CROP_OUTPUT_DIR_LONG_OPTION);\n        if (usesHancomAiOnly && !Config.HYBRID_HANCOM_AI.equals(config.getHybrid())) {\n            throw new IllegalArgumentException(\n                    \"Options --hybrid-hancom-ai-* require --hybrid=hancom-ai (got --hybrid=\"\n                    + config.getHybrid() + \")\");\n        }\n    }\n\n    /**\n     * Exports CLI option definitions as JSON for code generation.\n     * This is used to generate Node.js, Python, and documentation from a single\n     * source of truth.\n     *\n     * @param out The output stream to write JSON to\n     */\n    public static void exportOptionsAsJson(PrintStream out) {\n        List<OptionDefinition> exportable = OPTION_DEFINITIONS.stream()\n                .filter(d -> d.exported)\n                .collect(Collectors.toList());\n\n        // Build JSON manually to avoid external dependencies","sourceCodeStart":750,"sourceCodeEnd":786,"githubUrl":"https://github.com/opendataloader-project/opendataloader-pdf/blob/a7789b8e77dd05e2b8659eb3ea12fc458f80bfb8/java/opendataloader-pdf-core/src/main/java/org/opendataloader/pdf/api/cli/CLIOptions.java#L750-L786","documentation":"Thrown during CLI parsing when one or more --hybrid-hancom-ai-* options (regionlist-strategy, ocr-strategy, image-cache, save-crops, crop-output-dir) are present but --hybrid is not set to hancom-ai. These options only configure the Hancom AI backend, so the parser rejects them for any other backend to prevent silent misconfiguration. The check is an IllegalArgumentException raised in CLIOptions.applyOptions before any processing starts.","triggerScenarios":"Passing any of --hybrid-hancom-ai-regionlist-strategy, --hybrid-hancom-ai-ocr-strategy, --hybrid-hancom-ai-image-cache, --hybrid-hancom-ai-save-crops, or --hybrid-hancom-ai-crop-output-dir while --hybrid is unset, set to docling/docling-fast, or any value other than the literal 'hancom-ai' (compared at CLIOptions.java:767 against Config.HYBRID_HANCOM_AI).","commonSituations":"Copy-pasting Hancom-specific flags from a config meant for the Hancom backend while pointing --hybrid at docling; migrating backends and forgetting to switch the --hybrid value; stale flags left in a wrapper script or CI matrix; setting config.setHybrid() after the hancom-ai config fields are already populated via the API.","solutions":["Add --hybrid=hancom-ai to the same command line as the --hybrid-hancom-ai-* flags","Remove the --hybrid-hancom-ai-* options if you actually intend to run the docling/docling-fast backend","If configuring programmatically, call config.setHybrid(Config.HYBRID_HANCOM_AI) before or alongside setting HybridConfig fields"],"exampleFix":"// before\nopendataloader-pdf --hybrid=docling-fast --hybrid-hancom-ai-ocr-strategy force in.pdf\n// after\nopendataloader-pdf --hybrid=hancom-ai --hybrid-hancom-ai-ocr-strategy force in.pdf","handlingStrategy":"validation","validationCode":"// Validate before invoking CLIOptions.parse / building Config\nSet<String> hancomOnly = Set.of(\n    \"--hybrid-hancom-ai-regionlist-strategy\",\n    \"--hybrid-hancom-ai-ocr-strategy\",\n    \"--hybrid-hancom-ai-image-cache\",\n    \"--hybrid-hancom-ai-save-crops\",\n    \"--hybrid-hancom-ai-crop-output-dir\");\nboolean usesHancom = Arrays.stream(args).anyMatch(hancomOnly::contains);\nboolean isHancom = Arrays.stream(args)\n    .filter(a -> a.startsWith(\"--hybrid=\") && !a.startsWith(\"--hybrid-\"))\n    .anyMatch(a -> a.equals(\"--hybrid=hancom-ai\"));\nif (usesHancom && !isHancom) {\n    throw new IllegalArgumentException(\n        \"--hybrid-hancom-ai-* flags require --hybrid=hancom-ai\");\n}","typeGuard":null,"tryCatchPattern":"// If you cannot pre-validate, catch at parse time\ntry {\n    CLIOptions.parse(args, config);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"require --hybrid=hancom-ai\")) {\n        System.err.println(e.getMessage());\n        System.err.println(\"Re-run with --hybrid=hancom-ai or remove the hancom-only flags.\");\n        System.exit(2);\n    }\n    throw e;\n}","preventionTips":["Always pair --hybrid-hancom-ai-* with --hybrid=hancom-ai","Keep per-backend options in separate CLI profiles or config files","Add a wrapper-script assertion that checks backend/flag consistency before invoking the JAR"],"tags":["cli","config","validation","hybrid","hancom-ai"],"backgroundTag":null,"analyzedSha":"a7789b8e77dd05e2b8659eb3ea12fc458f80bfb8","analyzedAt":"2026-08-14T05:22:03.953Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}