{"record":{"id":"2b6983d5752a019d","repo":"langgenius/dify","slug":"knowledge-fs-base-url-must-not-include-credentials","errorCode":null,"errorMessage":"KNOWLEDGE_FS_BASE_URL must not include credentials, query, or fragment","messagePattern":"KNOWLEDGE_FS_BASE_URL must not include credentials, query, or fragment","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"api/configs/extra/knowledge_fs_config.py","lineNumber":53,"sourceCode":"        if isinstance(value, str):\n            normalized = value.strip()\n            return normalized or None\n        return value\n\n    @field_validator(\"KNOWLEDGE_FS_BASE_URL\")\n    @classmethod\n    def validate_base_url(cls, value: str | None) -> str | None:\n        if value is None:\n            return None\n        parsed = urlsplit(value)\n        if parsed.scheme not in {\"http\", \"https\"} or not parsed.netloc:\n            raise ValueError(\"KNOWLEDGE_FS_BASE_URL must be an absolute HTTP(S) URL\")\n        try:\n            _ = parsed.port\n        except ValueError as exc:\n            raise ValueError(\"KNOWLEDGE_FS_BASE_URL must include a valid port\") from exc\n        if parsed.username or parsed.password or parsed.query or parsed.fragment:\n            raise ValueError(\"KNOWLEDGE_FS_BASE_URL must not include credentials, query, or fragment\")\n        return value.rstrip(\"/\")\n\n    @model_validator(mode=\"after\")\n    def validate_enabled_connection(self) -> \"KnowledgeFSConfig\":\n        if not self.KNOWLEDGE_FS_ENABLED:\n            return self\n        if bool(self.KNOWLEDGE_FS_BASE_URL) != bool(self.KNOWLEDGE_FS_JWT_SECRET):\n            raise ValueError(\"KNOWLEDGE_FS_BASE_URL and KNOWLEDGE_FS_JWT_SECRET must be configured together\")\n        if not self.KNOWLEDGE_FS_BASE_URL:\n            raise ValueError(\"KnowledgeFS connection settings are required when the integration is enabled\")\n        return self\n","sourceCodeStart":35,"sourceCodeEnd":65,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/configs/extra/knowledge_fs_config.py#L35-L65","documentation":"Raised by KnowledgeFSConfig.validate_base_url when the parsed URL contains userinfo (username/password), a query string, or a fragment. The validator wants a clean origin URL because the gateway base is used verbatim to build outbound requests and sign JWTs; credentials must come from KNOWLEDGE_FS_JWT_SECRET, not the URL.","triggerScenarios":"Setting KNOWLEDGE_FS_BASE_URL to 'https://user:pass@kfs.example:8443', 'https://kfs.example:8443?token=x', or 'https://kfs.example:8443#section'.","commonSituations":"Copy-pasting a connection string from a secrets manager that bundles inline auth, or appending a query param expecting it to be forwarded to the gateway.","solutions":["Strip credentials, query, and fragment from the URL; supply only scheme://host:port.","Move authentication into KNOWLEDGE_FS_JWT_SECRET (min 32 chars) rather than the URL.","If a query/fragment appears unintentionally, remove trailing characters from the env value."],"exampleFix":"// before\nKNOWLEDGE_FS_BASE_URL=https://svc:pwd@kfs.example:8443?env=prod\n// after\nKNOWLEDGE_FS_BASE_URL=https://kfs.example:8443\nKNOWLEDGE_FS_JWT_SECRET=<32+ char shared secret>","handlingStrategy":"validation","validationCode":"from urllib.parse import urlsplit\n\ndef is_clean_origin(value: str) -> bool:\n    p = urlsplit(value)\n    return not (p.username or p.password or p.query or p.fragment)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store only scheme://host:port in KNOWLEDGE_FS_BASE_URL.","Keep secrets in dedicated env vars, not URL userinfo.","Run a startup assert that the parsed URL has empty userinfo/query/fragment."],"tags":["config","pydantic","knowledge-fs","security","url-validation"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}