{"record":{"id":"c7af8f9c332816a8","repo":"apache/seatunnel","slug":"config-validation-failed-c7af8f","errorCode":"CONFIG_VALIDATION_FAILED","errorMessage":"Cannot derive a safe logical source identity for Markdown input","messagePattern":"Cannot derive a safe logical source identity for Markdown input","errorType":"error_code","errorClass":"FileConnectorException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-file/connector-file-base/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/source/MarkdownKnowledgeSyncMetadata.java","lineNumber":60,"sourceCode":"    private static final char[] HEX_CHARS = \"0123456789abcdef\".toCharArray();\n    private static final KnowledgeSyncMetadataField[] BRIDGE_FIELDS = {\n        KnowledgeSyncMetadataField.SOURCE_URI,\n        KnowledgeSyncMetadataField.DOCUMENT_ID,\n        KnowledgeSyncMetadataField.DOCUMENT_HASH,\n        KnowledgeSyncMetadataField.CHUNK_HASH\n    };\n\n    private MarkdownKnowledgeSyncMetadata() {}\n\n    /**\n     * Builds a credential-free logical source identity without changing legacy physical identity.\n     *\n     * @param sourceUri physical source path or URI\n     * @return normalized local path or sanitized hierarchical remote URI\n     */\n    public static String canonicalizeSourceUri(String sourceUri) {\n        if (sourceUri == null || sourceUri.trim().isEmpty()) {\n            throw unsafeSourceIdentityException();\n        }\n        if (isWindowsLocalPath(sourceUri)) {\n            return sourceUri;\n        }\n\n        URI uri;\n        try {\n            uri = new URI(sourceUri);\n        } catch (URISyntaxException e) {\n            if (looksLikeUri(sourceUri)) {\n                throw unsafeSourceIdentityException();\n            }\n            return sourceUri;\n        }\n\n        if (uri.getScheme() == null) {\n            return sourceUri;\n        }","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-file/connector-file-base/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/source/MarkdownKnowledgeSyncMetadata.java#L42-L78","documentation":"MarkdownKnowledgeSyncMetadata.canonicalizeSourceUri derives a stable logical identity for a Markdown source. A null or whitespace-only sourceUri cannot identify anything, so it throws the unsafe-source-identity error (CONFIG_VALIDATION_FAILED) before the job starts reading files.","triggerScenarios":"Calling canonicalizeSourceUri (directly or via safeSourceContext) with sourceUri == null or sourceUri.trim().isEmpty() — typically because the file path/URI option was not populated in the connector config.","commonSituations":"Missing file path/URI in the Markdown source config; config templating left the placeholder empty; programmatic use passing an unset variable.","solutions":["Set the source path/URI option in the Markdown source config (a valid local path or hierarchical remote URI)","Check templated/variable-substituted config values actually resolved to non-empty strings at submit time","Validate config before submission; fail fast on empty required fields","If the path is intentionally optional, guard the call site and skip identity derivation"],"exampleFix":"// before\nMarkdownKnowledgeSyncMetadata.canonicalizeSourceUri(config.get(\"path\")); // path unset -> null\n// after\nString uri = config.getString(\"path\");\nObjects.requireNonNull(uri, \"Markdown source path must be set\");\nMarkdownKnowledgeSyncMetadata.canonicalizeSourceUri(uri);","handlingStrategy":"validation","validationCode":"String uri = config.getString(\"path\");\nif (uri == null || uri.trim().isEmpty())\n    throw new IllegalArgumentException(\"Markdown source path must be set\");","typeGuard":"boolean hasSourceUri(String s) { return s != null && !s.trim().isEmpty(); }","tryCatchPattern":"try {\n    String canonical = MarkdownKnowledgeSyncMetadata.canonicalizeSourceUri(uri);\n} catch (RuntimeException e) {\n    if (String.valueOf(e.getMessage()).contains(\"safe logical source identity\")) {\n        // fail config validation with a clear 'path is required' message\n    }\n}","preventionTips":["Make the path/URI option required in your config schema and validate at submit time","Check templated configs for unresolved placeholders before submission","Add a dry-run config validation step in CI","Fail fast with explicit messages instead of letting nulls reach connector internals"],"tags":["file","markdown","config-validation","null"],"backgroundTag":"empty-required-field","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}