{"record":{"id":"d0d3d4706b14dcdc","repo":"iflytek/astron-agent","slug":"both-api-key-and-secret-must-be-provided-for-ifly","errorCode":null,"errorMessage":"Both API key and secret must be provided for ifly authentication, or neither.","messagePattern":"Both API key and secret must be provided for ifly authentication, or neither\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"core/workflow/configs/app_config.py","lineNumber":322,"sourceCode":"            raise ValueError(\n                \"CODE_EXEC_MEMORY_LIMIT_MB must be between \"\n                f\"{MIN_CODE_EXEC_MEMORY_LIMIT_MB} and \"\n                f\"{MAX_CODE_EXEC_MEMORY_LIMIT_MB} MB\"\n            )\n        return v\n\n    @model_validator(mode=\"after\")\n    def validator_url(self) -> \"CodeExecutorConfig\":\n        \"\"\"\n        Validate the URL.\n\n        :return: The validated URL\n        \"\"\"\n        if self.exec_type in [\"ifly\", \"ifly-v2\"]:\n            if not self.url:\n                raise ValueError(\"URL is required for ifly or ifly-v2\")\n            if bool(self.api_key) != bool(self.api_secret):\n                raise ValueError(\n                    \"Both API key and secret must be provided for ifly authentication, or neither.\"\n                )\n        return self\n\n\nclass DatabaseConfig(BaseSettings):\n    \"\"\"\n    Database connection configuration.\n\n    Loads MySQL connection parameters from environment variables\n    (MYSQL_HOST, MYSQL_PORT, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DB).\n    \"\"\"\n\n    model_config = {\"env_prefix\": \"\", \"case_sensitive\": False}\n\n    host: str = Field(default=\"\", alias=\"MYSQL_HOST\")\n    port: str = Field(default=\"\", alias=\"MYSQL_PORT\")\n    user: str = Field(default=\"\", alias=\"MYSQL_USER\")","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/workflow/configs/app_config.py#L304-L340","documentation":"The same validator enforces that ifly/ifly-v2 authentication is all-or-nothing: api_key and api_secret must both be set or both be empty. Providing exactly one fails validation at startup, since asymmetric credentials cannot authenticate against the iFly backend.","triggerScenarios":"Setting CODE_EXEC_API_KEY without CODE_EXEC_API_SECRET (or vice versa) while exec_type is ifly/ifly-v2; one secret accidentally overridden to empty in an env overlay.","commonSituations":"Partial credential rotation in k8s secrets; pasting only the key from the iFly console and missing the secret field; config templates with one of the two fields commented out.","solutions":["Provide both CODE_EXEC_API_KEY and CODE_EXEC_API_SECRET","Or remove both to run unauthenticated (if permitted by the endpoint)","Check env overlays/secrets so one value isn't being emptied during deployment","Re-run the validator mentally against your final merged config, not just one source"],"exampleFix":"// before\nCODE_EXEC_API_KEY=abc123\n# secret missing\n// after\nCODE_EXEC_API_KEY=abc123\nCODE_EXEC_API_SECRET=xyz789","handlingStrategy":"validation","validationCode":"if exec_type in (\"ifly\", \"ifly-v2\") and bool(api_key) != bool(api_secret):\n    raise ValueError(\"Both API key and secret must be provided, or neither\")","typeGuard":null,"tryCatchPattern":"try:\n    AppConfig()\nexcept ValidationError as e:\n    logger.error(\"incomplete ifly credentials: %s\", e)\n    sys.exit(2)","preventionTips":["Store key+secret as a pair in the same secret object","Rotate credentials together","Keep both values in one env overlay to avoid partial overrides"],"tags":["config","authentication","validation"],"backgroundTag":"missing-credentials","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}