{"record":{"id":"839f2135c3d658c5","repo":"floci-io/floci","slug":"methodnotallowedexception","errorCode":"MethodNotAllowedException","errorMessage":"POST is not supported for ${serviceKey} tag resources; use PUT.","messagePattern":"POST is not supported for (.+?) tag resources; use PUT\\.","errorType":"http","errorClass":"AwsException","httpStatus":405,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/core/common/SharedTagsController.java","lineNumber":101,"sourceCode":"    }\n\n    @POST\n    @Consumes(MediaType.APPLICATION_JSON)\n    public Response tagResourceByBody(@Context HttpHeaders headers, String body) {\n        String arn = readResourceArn(body);\n        TagHandler handler = resolveHandler(arn);\n        return doTagResource(headers, handler, arn, body, Response.ok(objectMapper.createObjectNode()).build());\n    }\n\n    @POST\n    @Path(\"/{arn: .+}\")\n    @Consumes(MediaType.APPLICATION_JSON)\n    public Response tagResourcePost(@Context HttpHeaders headers,\n                                    @PathParam(\"arn\") String arn,\n                                    String body) {\n        TagHandler handler = resolveHandler(arn);\n        if (handler.tagResourceUsesPut()) {\n            throw new AwsException(\"MethodNotAllowedException\",\n                    \"POST is not supported for \" + handler.serviceKey() + \" tag resources; use PUT.\", 405);\n        }\n        return doTagResource(headers, handler, arn, body, Response.noContent().build());\n    }\n\n    @PUT\n    @Path(\"/{arn: .+}\")\n    @Consumes(MediaType.APPLICATION_JSON)\n    public Response tagResourcePut(@Context HttpHeaders headers,\n                                   @PathParam(\"arn\") String arn,\n                                   String body) {\n        TagHandler handler = resolveHandler(arn);\n        if (!handler.tagResourceUsesPut()) {\n            throw new AwsException(\"MethodNotAllowedException\",\n                    \"PUT is not supported for \" + handler.serviceKey() + \" tag resources; use POST.\", 405);\n        }\n        return doTagResource(headers, handler, arn, body, Response.noContent().build());\n    }","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/core/common/SharedTagsController.java#L83-L119","documentation":"Thrown by waitForCustomJob when a polled custom job is completed by the worker with status 'Failed'. The emulator creates a job for a Custom/ThirdParty action, waits while the worker polls/acknowledges/completes it, and on PutJobFailureResult reads result.failureDetails.message (defaulting to 'Custom action failed') to fail the pipeline action with ActionExecutionFailed.","triggerScenarios":"Worker calling PutJobFailureResult with failureDetails for the polled job; worker completing with a failure status through the emulator's job store; job result payload containing failureDetails.message set by the worker.","commonSituations":"Custom worker (e.g. external deployer) failing its task; worker pointing at the wrong job or reporting failure on timeout; integration tests asserting the failure path.","solutions":["Look at the failureDetails.message you (or your worker) sent with PutJobFailureResult — the pipeline error is only a relay","Fix the worker-side task that reported failure and re-run the pipeline execution","Include actionable context in failureDetails.message when reporting so the pipeline error is diagnosable"],"exampleFix":"// before\ncp.putJobFailureResult(r -> r.jobId(jobId).failureDetails(f -> f.type(FailureType.JobFailed).message(\"err\")));\n\n// after\ncp.putJobFailureResult(r -> r.jobId(jobId).failureDetails(f -> f.type(FailureType.JobFailed).message(\"deploy script exit 2: missing config/env\")));","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    client.startPipelineExecution(r -> r.name(name));\n} catch (ActionExecutionFailedException e) {\n    // message is the worker's failureDetails.message; route to on-call with the jobId\n    logger.error(\"custom action failed: {}\", e.getMessage());\n    throw e;\n}","preventionTips":["Always populate failureDetails.message with actionable context in PutJobFailureResult","Correlate worker logs by jobId so the relayed message can be traced to root cause"],"tags":["codepipeline","custom-action","job-worker","action-failed"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}