{"record":{"id":"8c746c320a1bbfe9","repo":"apache/seatunnel","slug":"accessid-and-accesskey-must-be-provided-when-sts-t","errorCode":null,"errorMessage":"accessId and accesskey must be provided when sts_token is used.","messagePattern":"accessId and accesskey must be provided when sts_token is used\\.","errorType":"validation","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-maxcompute/src/main/java/org/apache/seatunnel/connectors/seatunnel/maxcompute/util/MaxcomputeUtil.java","lineNumber":69,"sourceCode":"            tableTunnel.setEndpoint(readonlyConfig.get(MaxcomputeBaseOptions.TUNNEL_ENDPOINT));\n        }\n        if (StringUtils.isNotEmpty(readonlyConfig.get(MaxcomputeBaseOptions.TUNNEL_NAME))) {\n            tableTunnel\n                    .getConfig()\n                    .setQuotaName(readonlyConfig.get(MaxcomputeBaseOptions.TUNNEL_NAME));\n        }\n        return tableTunnel;\n    }\n\n    public static Account getAccount(ReadonlyConfig readonlyConfig) {\n        String stsToken = readonlyConfig.getOptional(MaxcomputeBaseOptions.STS_TOKEN).orElse(null);\n        String accessId = readonlyConfig.getOptional(MaxcomputeBaseOptions.ACCESS_ID).orElse(null);\n        String accessKey =\n                readonlyConfig.getOptional(MaxcomputeBaseOptions.ACCESS_KEY).orElse(null);\n\n        if (StringUtils.isNotEmpty(stsToken)) {\n            if (StringUtils.isEmpty(accessId) || StringUtils.isEmpty(accessKey)) {\n                throw new IllegalArgumentException(\n                        \"accessId and accesskey must be provided when sts_token is used.\");\n            }\n            return new StsAccount(accessId, accessKey, stsToken);\n        } else if (StringUtils.isNotEmpty(accessId) && StringUtils.isNotEmpty(accessKey)) {\n            return new AliyunAccount(accessId, accessKey);\n        } else {\n            return new AklessAccount(new DefaultCredentialsProvider());\n        }\n    }\n\n    public static Odps getOdps(ReadonlyConfig readonlyConfig) {\n        Account account = getAccount(readonlyConfig);\n        Odps odps = new Odps(account);\n        odps.setEndpoint(readonlyConfig.get(MaxcomputeBaseOptions.ENDPOINT));\n        odps.setDefaultProject(readonlyConfig.get(MaxcomputeBaseOptions.PROJECT));\n        odps.setCurrentSchema(\n                readonlyConfig.getOptional(MaxcomputeBaseOptions.SCHEMA_NAME).orElse(null));\n        return odps;","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-maxcompute/src/main/java/org/apache/seatunnel/connectors/seatunnel/maxcompute/util/MaxcomputeUtil.java#L51-L87","documentation":"MaxcomputeUtil.getAccount builds ODPS credentials from the job config. When an sts_token is supplied, the SDK also requires the matching accessId and accessKey (the STS temporary credentials' owner pair); if either is empty it throws IllegalArgumentException before any connection is attempted.","triggerScenarios":"Calling getAccount (via account()) with MaxcomputeBaseOptions.STS_TOKEN (or equivalent auth token) set in readonlyConfig while ACCESS_ID or ACCESS_KEY is null/empty.","commonSituations":"Users configure only an STS token thinking it is sufficient for authentication; partial copy-paste of Aliyun credential config; credentials supplied via env vars that are unset in the runtime environment.","solutions":["Add access_id and access_key alongside sts_token in the MaxCompute source/sink config.","If using environment-based credentials, verify the env vars are actually present in the runtime (container/task) environment.","If STS is not needed, remove sts_token so the plain accessId/accessKey path is used.","Check that the STS token was fetched together with its paired temporary AK/SK, not from a mismatched credential set."],"exampleFix":"// before\nMaxcompute {\n  url = \"...\"\n  sts_token = \"...\"\n}\n// after\nMaxcompute {\n  url = \"...\"\n  access_id = \"<sts-access-id>\"\n  access_key = \"<sts-access-key>\"\n  sts_token = \"...\"\n}","handlingStrategy":"validation","validationCode":"if (config.hasPath(\"sts_token\") && !config.getString(\"sts_token\").isEmpty()) {\n    if (!config.hasPath(\"access_id\") || config.getString(\"access_id\").isEmpty()\n        || !config.hasPath(\"access_key\") || config.getString(\"access_key\").isEmpty()) {\n        throw new IllegalArgumentException(\"access_id and access_key are required with sts_token\");\n    }\n}","typeGuard":"boolean stsCredentialsComplete(Map<String,String> cfg) {\n    boolean hasSts = cfg.get(\"sts_token\") != null && !cfg.get(\"sts_token\").isEmpty();\n    boolean hasAk = cfg.get(\"access_id\") != null && !cfg.get(\"access_id\").isEmpty()\n                 && cfg.get(\"access_key\") != null && !cfg.get(\"access_key\").isEmpty();\n    return !hasSts || hasAk;\n}","tryCatchPattern":"try {\n    Account account = MaxcomputeUtil.account(readonlyConfig);\n} catch (IllegalArgumentException e) {\n    throw new ConfigException(\"MaxCompute credential config incomplete: \" + e.getMessage());\n}","preventionTips":["Always ship the STS token together with its paired temporary accessId/accessKey","Pre-validate credential config in CI before job submission","Never source credentials from env vars without checking presence at startup"],"tags":["maxcompute","authentication","sts","config"],"backgroundTag":"missing-credentials","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}