{"record":{"id":"e1d6d90cb78c9f7e","repo":"apereo/cas","slug":"invalid-request-e1d6d9","errorCode":"INVALID_REQUEST","errorMessage":"Could not identify service and/or service ticket for service: [{}]","messagePattern":"Could not identify service and/or service ticket for service: \\[(.+?)\\]","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"support/cas-server-support-validation-core/src/main/java/org/apereo/cas/web/AbstractServiceValidateController.java","lineNumber":92,"sourceCode":"\n    protected Ticket handleProxyGrantingTicketDelivery(final String serviceTicketId, final Credential credential) throws Throwable {\n        val serviceTicket = serviceValidateConfigurationContext.getTicketRegistry().getTicket(serviceTicketId, ServiceTicket.class);\n        val authenticationResult = serviceValidateConfigurationContext.getAuthenticationSystemSupport()\n            .finalizeAuthenticationTransaction(serviceTicket.getService(), credential);\n        val proxyGrantingTicket = serviceValidateConfigurationContext.getCentralAuthenticationService()\n            .createProxyGrantingTicket(serviceTicketId, authenticationResult);\n        LOGGER.debug(\"Generated proxy-granting ticket [{}] off of service ticket [{}] and credential [{}]\",\n            proxyGrantingTicket.getId(), serviceTicketId, credential);\n        return proxyGrantingTicket;\n    }\n\n    @Override\n    public ModelAndView handleRequestInternal(final HttpServletRequest request,\n                                              final HttpServletResponse response) throws Exception {\n        val service = serviceValidateConfigurationContext.getArgumentExtractor().extractService(request);\n        val serviceTicketId = Optional.ofNullable(service).map(WebApplicationService::getArtifactId).orElse(null);\n        if (service == null || StringUtils.isBlank(serviceTicketId)) {\n            LOGGER.warn(\"Could not identify service and/or service ticket for service: [{}]\", service);\n            return generateErrorView(CasProtocolConstants.ERROR_CODE_INVALID_REQUEST, StringUtils.EMPTY, request, service);\n        }\n        try {\n            prepareForTicketValidation(request, service, serviceTicketId);\n            return handleTicketValidation(request, response, service, serviceTicketId);\n        } catch (final AbstractTicketValidationException e) {\n            val code = e.getCode();\n            val description = getTicketValidationErrorDescription(code,\n                new Object[]{serviceTicketId, e.getService().getId(), service.getId()}, request);\n            return generateErrorView(code, description, request, service);\n        } catch (final AbstractTicketException e) {\n            val description = getTicketValidationErrorDescription(e.getCode(), new Object[]{serviceTicketId}, request);\n            return generateErrorView(e.getCode(), description, request, service);\n        } catch (final UnauthorizedProxyingException e) {\n            val description = getTicketValidationErrorDescription(\n                CasProtocolConstants.ERROR_CODE_UNAUTHORIZED_SERVICE_PROXY, new Object[]{service.getId()}, request);\n            return generateErrorView(CasProtocolConstants.ERROR_CODE_UNAUTHORIZED_SERVICE_PROXY, description, request, service);\n        } catch (final UnauthorizedServiceException | PrincipalException e) {","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-validation-core/src/main/java/org/apereo/cas/web/AbstractServiceValidateController.java#L74-L110","documentation":"In handleRequestInternal of the service validation controller, the request was missing either the service parameter or a service ticket (artifact), so CAS cannot even begin validation. It returns the error view with code INVALID_REQUEST.","triggerScenarios":"The argument extractor's extractService(request) returns null, or the extracted service's getArtifactId() is blank — i.e. a GET/POST to /serviceValidate or /p3/serviceValidate without both 'service' and 'ticket' query parameters.","commonSituations":"Client library dropping the ticket parameter after redirect back; manual curl tests hitting the endpoint without parameters; misconfigured callback URL truncating the query string; custom argument extractor not recognizing the service format.","solutions":["Ensure the client calls validation with both parameters, e.g. /p3/serviceValidate?service=<registered-url>&ticket=ST-....","Fix the client's callback/service URL so the ticket query parameter is preserved and not truncated (no missing '?', no aggressive URL rewriting).","If using a custom service format, register the appropriate ArgumentExtractor so the service can be extracted from the request."],"exampleFix":"// before\ncurl 'https://cas.example.org/cas/p3/serviceValidate?ticket=ST-1-abc'\n\n// after\ncurl 'https://cas.example.org/cas/p3/serviceValidate?service=https%3A%2F%2Fmyapp.example.org%2Flogin&ticket=ST-1-abc'","handlingStrategy":"validation","validationCode":"// before calling the CAS validation endpoint\nif (!serviceUrl || !ticketId) {\n  throw new Error('Both service and ticket parameters are required for CAS validation');\n}\nconst url = `${casBaseUrl}/p3/serviceValidate?service=${encodeURIComponent(serviceUrl)}&ticket=${encodeURIComponent(ticketId)}`;","typeGuard":null,"tryCatchPattern":"try {\n    // call validation endpoint\n} catch (err) {\n    // check for INVALID_REQUEST code: missing service/ticket params\n}","preventionTips":["Always URL-encode service and ticket values in the validation request.","Verify the CAS callback URL preserves its full query string through redirects and proxies.","Use a maintained CAS client library instead of hand-built validation URLs."],"tags":["cas-protocol","ticket-validation","missing-parameter","invalid-request"],"backgroundTag":"missing-required-argument","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}