INVALID_ARGUMENT when sending HTTP/POST via Cloud Scheduler to Cloud Run Function

I’m currently trying to setup a simple Cloud Scheduler and Cloud Run Function combination, as outlines in https://cloud.google.com/scheduler/docs/tut-gcf-http.

Followed this guide, successfully deployed my Function (which works when tested locally using `functions-framework`) and setup the Cloud Scheduler Job. Settings look as follows:


resource "google_cloud_scheduler_job" "scheduled-export" {
  name        = "scheduled-export"
  # Monthly, at the first of the month at 3am
  schedule         = "0 3 1 * *"
  time_zone        = "Europe/Berlin"
  attempt_deadline = "60s"

  retry_config {
    retry_count = 1
  }

  http_target {
    http_method = "POST"
    uri         = module.export-func.uri
    oidc_token {
      service_account_email = module.scheduler-account.email
    }
    body = base64encode(jsonencode({
      output_bucket = module.export-bucket.name
    }))
    headers = {
      "Content-Type" = "application/json"
    }
  }
}

`module.export-func.uri` is using the Cloud Fabric Module to create a Cloud Function and retrieves its non-deterministic URI. Bucket and Service Account are created in a similar fashion and deploy successfully.

Now, once I select Force Run on the Cloud Scheduler Task, it results in an HTTP/400 with INVALID_ARGUMENT being returned. Logs on Cloud Scheduler side look as follows:

{
  "insertId": "REDACTED",
  "jsonPayload": {
    "@type": "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished",
    "status": "INVALID_ARGUMENT",
    "jobName": "projects/REDACTED/locations/REDACTED/jobs/scheduled-export",
    "debugInfo": "URL_ERROR-ERROR_OTHER. Original HTTP response code number = 400",
    "targetType": "HTTP",
    "url": "https://REDACTED.a.run.app/"
  },
  "httpRequest": {
    "status": 400
  },
  "resource": {
    "type": "cloud_scheduler_job",
    "labels": {
      "project_id": "REDACTED",
      "location": "REDACTED",
      "job_id": "scheduled-export"
    }
  },
  "timestamp": "2025-09-08T12:39:19.861522148Z",
  "severity": "ERROR",
  "logName": "projects/REDACTED/logs/cloudscheduler.googleapis.com%2Fexecutions",
  "receiveTimestamp": "2025-09-08T12:39:19.861522148Z"
}

Here is the log entry of the Cloud Run Function Service:

{
  "httpRequest": {
    "cacheFillBytes": "0",
    "cacheHit": false,
    "cacheLookup": false,
    "cacheValidatedWithOriginServer": false,
    "latency": "0.012s",
    "protocol": "HTTP/1.1",
    "requestMethod": "POST",
    "requestSize": "1296",
    "requestUrl": "https://REDACTED.a.run.app/",
    "responseSize": "413",
    "status": 400,
    "userAgent": "Google-Cloud-Scheduler"
  },
  "logName": "projects/REDACTED/logs/run.googleapis.com%2Frequests",
  "payload": "payloadNotSet",
  "receiveLocation": "REDACTED",
  "receiveTimestamp": "2025-09-08T12:47:03.446740874Z",
  "severity": "WARNING",
  "timestamp": "2025-09-08T12:47:03.411460Z",
  "traceSampled": true
}

Everything is set up in the same Region, same Project.
Upon manual inspection of the Cloud Scheduler Job, things are correctly entered. Body is set to a JSON string (not escaped, literally written as minified JSON), OIDC points to the correct account. Cloud Function URI is filled out.

My attention was caught by the element .payload being “payloadNotSet”, which indicates that the body is not being submitted correctly to the Cloud Function. But this is pure speculation. The error message is not very verbose, doesn’t tell me anything about what argument/parameter it is unhappy about and the logs seem to lack critical information.

My Function may also return HTTP/400, but would do so in a more verbose way, returning an error message including a payload, explaining what went wrong and how to fix it. This would appear in the Cloud Run logs, I suppose - but it doesn’t.

So this error, as far as I can tell, is produced by Google Cloud when invoking the Cloud Function.

However, my resource structure here is already so simple, that I cannot see any room for error really. Threads like INVALID_ARGUMENT occurs when trying to pass request body from Cloud Scheduler to Cloud Run Job use a slightly different approach and/or I wasn’t able to reproduce this solution for me.

I’m really frustrated after several hours of debugging such a basic functionality. I’m afraid to miss something blatently obvious, but I’m successfully deploying, permissions are not the culprit (according to the error message, which mentions arguments), so what could this be? Why is Cloud Functions rejecting my invocation?

Edit: After redeploying my Terraform code, the error became a HTTP/403 Unauthorized, despite the Service Account it is run as, being correct and not having changed. I double checked that this Account has the Invoker role.

Just to be sure, I re-ran Terraform, making sure that there is no state-drift. Running the Cloud Scheduler again changed the error into HTTP/500 URL unreachable. At this point, I’m not sure if Google is being serious here.

How can it be, that Cloud Scheduler, a glorified Crontab, is THAT difficult to configure while not providing any trace of what its errors mean? It literally takes me more time to debug this single scheduled invocation, that it took me to develop the entire Function. I might just consider dropping GCP and switching to GitHub Workflows to invoke it, since it works reliably and clearly states what is wrong.

Hi inst4ll,

The HTTP 400 INVALID_ARGUMENT error in the Cloud Scheduler logs seems to be due to the misconfiguration of the body payload or other related issue.

Try any of these steps to troubleshoot:

  • Review your job configuration. According to the Cloud Build REST API reference, the correct body format for the projects.triggers.run method should be a RepoSource object. There’s a possibility that the current request body incorrectly uses a source field, which is not part of the expected schema.

  • Try to double-check the uri = module.export-func.uri within the http_target configuration. If the URI is being generated non-deterministically, it could potentially include invalid or unexpected values. According from this documentation:

    The full URI path that the request will be sent to. This string must begin with either “http://” or “https://”. Some examples of valid values for uri are: http://acme.com and https://acme.com/sales:8080. Cloud Scheduler will encode some characters for safety and compatibility. The maximum allowed URL length is 2083 characters after encoding.

  • In the Cloud Schedule UI when creating a job, make sure to expand the ‘Configure the execution’ section and configure it properly, rather than directly clicking the CREATE button – otherwise, the job will be created with an empty body.

  • You also mentioned in your edits that you’ve encountered an HTTP 403 error. You may refer to Job fails with a permission error, as you might need to complete one or more verifications to proceed. As for the HTTP 500 error, it could be a transient condition, such as an overloaded server. Check Job fails due to unreachable destination target, you’ll find all the possible scenarios explaining why the job fails.