{"record":{"id":"0b4c37ca74c60fb6","repo":"prestodb/presto","slug":"generic-user-error-0b4c37","errorCode":"GENERIC_USER_ERROR","errorMessage":"GENERIC_USER_ERROR: failureInfo.toException() (decoded failure thrown to user via fail() function)","messagePattern":"GENERIC_USER_ERROR: failureInfo\\.toException\\(\\) \\(decoded failure thrown to user via fail\\(\\) function\\)","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/operator/scalar/FailureFunction.java","lineNumber":42,"sourceCode":"import io.airlift.slice.Slice;\n\nimport static com.facebook.presto.spi.function.SqlFunctionVisibility.HIDDEN;\n\npublic final class FailureFunction\n{\n    private static final JsonCodec<FailureInfo> JSON_CODEC = JsonCodec.jsonCodec(FailureInfo.class);\n\n    private FailureFunction() {}\n\n    // We shouldn't be using UNKNOWN as an explicit type. This will be fixed when we fix type inference\n    @Description(\"Decodes json to an exception and throws it\")\n    @ScalarFunction(value = \"fail\", visibility = HIDDEN)\n    @SqlType(\"unknown\")\n    public static boolean failWithException(@SqlType(StandardTypes.JSON) Slice failureInfoSlice)\n    {\n        FailureInfo failureInfo = JSON_CODEC.fromJson(failureInfoSlice.getBytes());\n        // wrap the failure in a new exception to append the current stack trace\n        throw new PrestoException(StandardErrorCode.GENERIC_USER_ERROR, failureInfo.toException());\n    }\n\n    // This function is only used to propagate optimization failures.\n    @Description(\"Decodes json to an exception and throws it with supplied errorCode\")\n    @ScalarFunction(value = \"fail\", visibility = HIDDEN)\n    @SqlType(\"unknown\")\n    public static boolean failWithException(\n            @SqlType(StandardTypes.INTEGER) long errorCode,\n            @SqlType(StandardTypes.JSON) Slice failureInfoSlice)\n    {\n        FailureInfo failureInfo = JSON_CODEC.fromJson(failureInfoSlice.getBytes());\n        // wrap the failure in a new exception to append the current stack trace\n        for (StandardErrorCode standardErrorCode : StandardErrorCode.values()) {\n            if (standardErrorCode.toErrorCode().getCode() == errorCode) {\n                throw new PrestoException(standardErrorCode, failureInfo.toException());\n            }\n        }\n        throw new PrestoException(StandardErrorCode.GENERIC_INTERNAL_ERROR, \"Unable to find error for code: \" + errorCode, failureInfo.toException());","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/operator/scalar/FailureFunction.java#L24-L60","documentation":"The hidden SQL fail(json) function deserializes a serialized FailureInfo (PrestoException JSON) and throws it as a new PrestoException wrapped in GENERIC_USER_ERROR. This is how Presto propagates an error that occurred during query optimization back to the user at execution time, appending the current stack trace. Seeing this message means the original error was deliberately deferred from planning and re-thrown here.","triggerScenarios":"A query calls fail(json_failure_info) (internally injected by the optimizer when an error is raised during planning via the FailFunction), where the JSON argument decodes to a FailureInfo. The decoded failure is then thrown with code GENERIC_USER_ERROR regardless of the original code.","commonSituations":"Developers hit this when a query plan contains a fail() call injected for an optimization-time error: bad literal usage, unsupported function arguments, or a type error detected during planning that surfaces only when the fragment executes. It also appears when hand-crafting SQL that calls fail() with a serialized exception JSON.","solutions":["Read the inner failureInfo message/stack in the error to find the original optimization failure and fix its root cause.","Inspect the query fragment containing the injected fail(json) call to identify which expression triggered the deferred error.","If calling fail() manually, pass a valid JSON FailureInfo produced by serializing a PrestoException, not arbitrary JSON."],"exampleFix":"// before\nSELECT fail('{\"message\":\"some error\"}')\n// after\n-- fix the underlying expression instead of relying on the deferred failure","handlingStrategy":"try-catch","validationCode":"// SQL: avoid reaching the injected fail(json) by validating inputs at query build time\n-- ensure literals/arguments passed the planner checks before execution","typeGuard":null,"tryCatchPattern":"// client\ntry {\n    executeQuery(sql);\n} catch (QueryFailedException e) {\n    if (e.getErrorCode().getCode() == StandardErrorCode.GENERIC_USER_ERROR.toErrorCode().getCode()) {\n        // inspect failureInfo in the failure JSON for the original cause\n    }\n}","preventionTips":["Read the inner failureInfo stack trace to locate the real planning error","Validate query arguments before submission rather than relying on runtime failure","Keep planner/version assumptions current when upgrading Presto"],"tags":["sql","presto","error-propagation","generic-user-error"],"backgroundTag":"deferred-query-error","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}