googleapis/mcp-toolbox · warning
job has no placement info
Error message
job has no placement info
What it means
JobLogsURLFromProto builds a Console Cloud Logging URL for a job and requires jobPb.Placement.ClusterName. If the Job proto's Placement field is nil, there is no cluster name to embed in the URL, so this sentinel error is returned. It propagates to ToJobs (ListJobs) and GetJob.
Source
Thrown at internal/sources/dataproc/url.go:68
if !stateStartTime.IsZero() {
endTime = stateStartTime
startTime = stateStartTime.Add(-1 * time.Hour)
}
}
}
return ClusterLogsURL(clusterPb.ProjectId, region, clusterPb.ClusterName, clusterPb.ClusterUuid, startTime, endTime)
}
// JobConsoleURLFromProto builds a URL to the Google Cloud Console linking to the job page.
func JobConsoleURLFromProto(jobPb *dataprocpb.Job, region string) string {
return JobConsoleURL(jobPb.Reference.ProjectId, region, jobPb.Reference.JobId)
}
// JobLogsURLFromProto builds a URL to the Google Cloud Console showing Cloud Logging for the given job.
func JobLogsURLFromProto(jobPb *dataprocpb.Job, region string) (string, error) {
if jobPb.Placement == nil {
return "", fmt.Errorf("job has no placement info")
}
clusterName := jobPb.Placement.ClusterName
projectID := jobPb.Reference.ProjectId
jobID := jobPb.Reference.JobId
var startTime, endTime time.Time
// Find min start time from history
for _, s := range jobPb.StatusHistory {
t := s.StateStartTime.AsTime()
if startTime.IsZero() || t.Before(startTime) {
startTime = t
}
}
// Also check current status
if jobPb.Status != nil {
t := jobPb.Status.StateStartTime.AsTime()
if startTime.IsZero() || t.Before(startTime) {
startTime = tView on GitHub (pinned to 8cc6e09de2)
Solutions
- Guard the call: check jobPb.Placement != nil before calling JobLogsURLFromProto
- In tests, populate dataprocpb.Job{Placement: &dataprocpb.JobPlacement{ClusterName: "..."}}
- Fall back to a console URL variant that does not require the cluster name when placement is absent
Example fix
// before
logsUrl, err := JobLogsURLFromProto(jobPb, region)
// after
var logsUrl string
if jobPb.GetPlacement() != nil {
logsUrl, _ = JobLogsURLFromProto(jobPb, region)
} Defensive patterns
Strategy: type-guard
Validate before calling
if jobPb.GetPlacement() == nil || jobPb.GetPlacement().GetClusterName() == "" {
return "", fmt.Errorf("job has no placement info")
} Type guard
func jobHasPlacement(j *dataprocpb.Job) bool {
return j != nil && j.GetPlacement() != nil && j.GetPlacement().GetClusterName() != ""
} Try / catch
var logsUrl string
if jobHasPlacement(jobPb) {
logsUrl, _ = JobLogsURLFromProto(jobPb, region)
} Prevention
- Always use generated getters (GetPlacement) which are nil-safe
- In tests, populate Placement with a ClusterName
- Prefer degrading to no URL over propagating an error
When it happens
Trigger: Passing a *dataprocpb.Job with Placement == nil to JobLogsURLFromProto — directly in tests (TestJobLogsURLFromProto) or indirectly via ToJobs/GetJob when the API returns a placement-less job.
Common situations: Unit tests constructing minimal Job protos without placement; API responses for jobs in edge states lacking placement metadata.
Related errors
- error generating logs url: %v
- failed to create dataproc client: %w
- failed to create longrunning client: %w
- failed to create dataproc job client: %w
- failed to list clusters: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/51f0f5f038f498b2.
Report an issue: GitHub.