Skip to content

Invalid schema for function 'xxx': In context=(), object schema missing properties. When tool doesn't have any paramters #4776

@salaboy

Description

@salaboy

Please do a quick search on GitHub issues first, there might be already a duplicate issue for the one you are about to create.
If the bug is trivial, just go ahead and create the issue. Otherwise, please take a few moments and fill in the following sections:

Bug description

Getting this exception:

Invalid schema for function 'xxx': In context=(), object schema missing properties.

I think this happens only when the tool has no parameters. Check the example below:

2025-10-31T13:46:54.123Z  WARN 41701 --- [agent] [pool-4-thread-1] o.s.a.r.a.SpringAiRetryAutoConfiguration : Retry error. Retry count: 1, Exception: HTTP 400 - {
  "error": {
    "message": "Invalid schema for function 'k8s_get_available_api_resources': In context=(), object schema missing properties.",
    "type": "invalid_request_error",
    "param": "tools[9].function.parameters",
    "code": "invalid_function_parameters"
  }
}

org.springframework.ai.retry.NonTransientAiException: HTTP 400 - {
  "error": {
    "message": "Invalid schema for function 'k8s_get_available_api_resources': In context=(), object schema missing properties.",
    "type": "invalid_request_error",
    "param": "tools[9].function.parameters",
    "code": "invalid_function_parameters"
  }
}
        at org.springframework.ai.retry.autoconfigure.SpringAiRetryAutoConfiguration$2.handleError(SpringAiRetryAutoConfiguration.java:109) ~[spring-ai-autoconfigure-retry-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:58) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.StatusHandler.lambda$fromErrorHandler$1(StatusHandler.java:71) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.StatusHandler.handle(StatusHandler.java:146) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.applyStatusHandlers(DefaultRestClient.java:838) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.lambda$readBody$4(DefaultRestClient.java:827) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.DefaultRestClient.readWithMessageConverters(DefaultRestClient.java:216) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.readBody(DefaultRestClient.java:826) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.lambda$toEntityInternal$2(DefaultRestClient.java:782) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:586) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchange(DefaultRestClient.java:540) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.RestClient$RequestHeadersSpec.exchange(RestClient.java:680) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.executeAndExtract(DefaultRestClient.java:821) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.toEntityInternal(DefaultRestClient.java:781) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.web.client.DefaultRestClient$DefaultResponseSpec.toEntity(DefaultRestClient.java:770) ~[spring-web-6.2.11.jar:6.2.11]
        at org.springframework.ai.openai.api.OpenAiApi.chatCompletionEntity(OpenAiApi.java:212) ~[spring-ai-openai-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at org.springframework.ai.openai.OpenAiChatModel.lambda$internalCall$1(OpenAiChatModel.java:200) ~[spring-ai-openai-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:357) ~[spring-retry-2.0.12.jar:na]
        at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:230) ~[spring-retry-2.0.12.jar:na]
        at org.springframework.ai.openai.OpenAiChatModel.lambda$internalCall$3(OpenAiChatModel.java:200) ~[spring-ai-openai-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at io.micrometer.observation.Observation.observe(Observation.java:564) ~[micrometer-observation-1.15.4.jar:1.15.4]
        at org.springframework.ai.openai.OpenAiChatModel.internalCall(OpenAiChatModel.java:197) ~[spring-ai-openai-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at org.springframework.ai.openai.OpenAiChatModel.call(OpenAiChatModel.java:182) ~[spring-ai-openai-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at org.springframework.ai.chat.client.advisor.ChatModelCallAdvisor.adviseCall(ChatModelCallAdvisor.java:54) ~[spring-ai-client-chat-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at org.springframework.ai.chat.client.advisor.DefaultAroundAdvisorChain.lambda$nextCall$1(DefaultAroundAdvisorChain.java:113) ~[spring-ai-client-chat-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at io.micrometer.observation.Observation.observe(Observation.java:564) ~[micrometer-observation-1.15.4.jar:1.15.4]
        at org.springframework.ai.chat.client.advisor.DefaultAroundAdvisorChain.nextCall(DefaultAroundAdvisorChain.java:112) ~[spring-ai-client-chat-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.lambda$doGetObservableChatClientResponse$1(DefaultChatClient.java:520) ~[spring-ai-client-chat-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at io.micrometer.observation.Observation.observe(Observation.java:564) ~[micrometer-observation-1.15.4.jar:1.15.4]
        at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.doGetObservableChatClientResponse(DefaultChatClient.java:518) ~[spring-ai-client-chat-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.doGetObservableChatClientResponse(DefaultChatClient.java:497) ~[spring-ai-client-chat-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at org.springframework.ai.chat.client.DefaultChatClient$DefaultCallResponseSpec.content(DefaultChatClient.java:492) ~[spring-ai-client-chat-1.1.0-SNAPSHOT.jar:1.1.0-SNAPSHOT]
        at com.salaboy.platform.agent.CheckPlatformCapabilitiesActivity.run(CheckPlatformCapabilitiesActivity.java:42) ~[classes/:na]
        at io.dapr.workflows.runtime.WorkflowActivityInstanceWrapper.lambda$create$0(WorkflowActivityInstanceWrapper.java:54) ~[dapr-sdk-workflows-1.16.1-rc-2.jar:na]
        at io.dapr.durabletask.TaskActivityExecutor.execute(TaskActivityExecutor.java:38) ~[durabletask-client-1.5.10.jar:na]
        at io.dapr.durabletask.DurableTaskGrpcWorker.lambda$startAndBlock$1(DurableTaskGrpcWorker.java:199) ~[durabletask-client-1.5.10.jar:na]
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) ~[na:na]
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[na:na]
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[na:na]
        at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
Image

Request:

{
  "method": "tools/call",
  "params": {
    "name": "k8s_get_available_api_resources",
    "arguments": {},
    "_meta": {
      "progressToken": 2
    }
  }
}

Response:

{
  "content": [
    {
      "type": "text",
      "text": "NAME                                SHORTNAMES   APIVERSION                        NAMESPACED   KIND\nbindings                                         v1                                true         Binding\ncomponentstatuses                   cs           v1                                false        ComponentStatus\nconfigmaps                          cm           v1                                true         ConfigMap\nendpoints                           ep           v1                                true         Endpoints\nevents                              ev           v1                                true         Event\nlimitranges                         limits       v1                                true         LimitRange\nnamespaces                          ns           v1                                false        Namespace\nnodes                               no           v1                                false        Node\npersistentvolumeclaims              pvc          v1                                true         PersistentVolumeClaim\npersistentvolumes                   pv           v1                                false        PersistentVolume\npods                                po           v1                                true         Pod\npodtemplates                                     v1                                true         PodTemplate\nreplicationcontrollers              rc           v1                                true         ReplicationController\nresourcequotas                      quota        v1                                true         ResourceQuota\nsecrets                                          v1                                true         Secret\nserviceaccounts                     sa           v1                                true         ServiceAccount\nservices                            svc          v1                                true         Service\nmutatingwebhookconfigurations                    admissionregistration.k8s.io/v1   false        MutatingWebhookConfiguration\nvalidatingadmissionpolicies                      admissionregistration.k8s.io/v1   false        ValidatingAdmissionPolicy\nvalidatingadmissionpolicybindings                admissionregistration.k8s.io/v1   false        ValidatingAdmissionPolicyBinding\nvalidatingwebhookconfigurations                  admissionregistration.k8s.io/v1   false        ValidatingWebhookConfiguration\ncustomresourcedefinitions           crd,crds     apiextensions.k8s.io/v1           false        CustomResourceDefinition\napiservices                                      apiregistration.k8s.io/v1         false        APIService\ncontrollerrevisions                              apps/v1                           true         ControllerRevision\ndaemonsets                          ds           apps/v1                           true         DaemonSet\ndeployments                         deploy       apps/v1                           true         Deployment\nreplicasets                         rs           apps/v1                           true         ReplicaSet\nstatefulsets                        sts          apps/v1                           true         StatefulSet\nselfsubjectreviews                               authentication.k8s.io/v1          false        SelfSubjectReview\ntokenreviews                                     authentication.k8s.io/v1          false        TokenReview\nlocalsubjectaccessreviews                        authorization.k8s.io/v1           true         LocalSubjectAccessReview\nselfsubjectaccessreviews                         authorization.k8s.io/v1           false        SelfSubjectAccessReview\nselfsubjectrulesreviews                          authorization.k8s.io/v1           false        SelfSubjectRulesReview\nsubjectaccessreviews                             authorization.k8s.io/v1           false        SubjectAccessReview\nhorizontalpodautoscalers            hpa          autoscaling/v2                    true         HorizontalPodAutoscaler\ncronjobs                            cj           batch/v1                          true         CronJob\njobs                                             batch/v1                          true         Job\ncertificatesigningrequests          csr          certificates.k8s.io/v1            false        CertificateSigningRequest\nleases                                           coordination.k8s.io/v1            true         Lease\nendpointslices                                   discovery.k8s.io/v1               true         EndpointSlice\nevents                              ev           events.k8s.io/v1                  true         Event\nflowschemas                                      flowcontrol.apiserver.k8s.io/v1   false        FlowSchema\nprioritylevelconfigurations                      flowcontrol.apiserver.k8s.io/v1   false        PriorityLevelConfiguration\nagents                                           kagent.dev/v1alpha2               true         Agent\nmcpservers                                       kagent.dev/v1alpha1               true         MCPServer\nmemories                                         kagent.dev/v1alpha1               true         Memory\nmodelconfigs                        mc           kagent.dev/v1alpha2               true         ModelConfig\nremotemcpservers                    rmcps        kagent.dev/v1alpha2               true         RemoteMCPServer\ntoolservers                         ts           kagent.dev/v1alpha1               true         ToolServer\ningressclasses                                   networking.k8s.io/v1              false        IngressClass\ningresses                           ing          networking.k8s.io/v1              true         Ingress\nipaddresses                         ip           networking.k8s.io/v1              false        IPAddress\nnetworkpolicies                     netpol       networking.k8s.io/v1              true         NetworkPolicy\nservicecidrs                                     networking.k8s.io/v1              false        ServiceCIDR\nruntimeclasses                                   node.k8s.io/v1                    false        RuntimeClass\npoddisruptionbudgets                pdb          policy/v1                         true         PodDisruptionBudget\nclusterrolebindings                              rbac.authorization.k8s.io/v1      false        ClusterRoleBinding\nclusterroles                                     rbac.authorization.k8s.io/v1      false        ClusterRole\nrolebindings                                     rbac.authorization.k8s.io/v1      true         RoleBinding\nroles                                            rbac.authorization.k8s.io/v1      true         Role\npriorityclasses                     pc           scheduling.k8s.io/v1              false        PriorityClass\ncsidrivers                                       storage.k8s.io/v1                 false        CSIDriver\ncsinodes                                         storage.k8s.io/v1                 false        CSINode\ncsistoragecapacities                             storage.k8s.io/v1                 true         CSIStorageCapacity\nstorageclasses                      sc           storage.k8s.io/v1                 false        StorageClass\nvolumeattachments                                storage.k8s.io/v1                 false        VolumeAttachment\n"
    }
  ]
}

Environment

Connecting Spring AI MCP Client to Kagent (https://kagent.dev) MCP Server.

Steps to reproduce
Steps to reproduce the issue.

Expected behavior
A clear and concise description of what you expected to happen.

Minimal Complete Reproducible example
Please provide a failing test or a minimal complete verifiable example that reproduces the issue.
Bug reports that are reproducible will take priority in resolution over reports that are not reproducible.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions