{"record":{"id":"80cb7c5dace4d8b3","repo":"hashicorp/terraform","slug":"lock-id-should-be-numerical-value-got-s","errorCode":null,"errorMessage":"Lock ID should be numerical value, got '%s'","messagePattern":"Lock ID should be numerical value, got '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/gcs/client.go","lineNumber":131,"sourceCode":"\t\t}\n\t\treturn w.Close()\n\t}()\n\n\tif err != nil {\n\t\treturn \"\", c.lockError(fmt.Errorf(\"writing %q failed: %v\", c.lockFileURL(), err))\n\t}\n\n\tinfo.ID = strconv.FormatInt(w.Attrs().Generation, 10)\n\n\treturn info.ID, nil\n}\n\nfunc (c *remoteClient) Unlock(id string) error {\n\tctx := context.TODO()\n\n\tgen, err := strconv.ParseInt(id, 10, 64)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"Lock ID should be numerical value, got '%s'\", id)\n\t}\n\n\tif err := c.lockFile().If(storage.Conditions{GenerationMatch: gen}).Delete(ctx); err != nil {\n\t\treturn c.lockError(err)\n\t}\n\n\treturn nil\n}\n\nfunc (c *remoteClient) lockError(err error) *statemgr.LockError {\n\tlockErr := &statemgr.LockError{\n\t\tErr: err,\n\t}\n\n\tinfo, infoErr := c.lockInfo()\n\tif infoErr != nil {\n\t\tlockErr.Err = errors.Join(lockErr.Err, infoErr)\n\t} else {","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/backend/remote-state/gcs/client.go#L113-L149","documentation":"Thrown by Unlock when the supplied lock ID cannot be parsed as a 64-bit integer. GCS lock IDs are object generation numbers (numeric), so Unlock strconv.ParseInt's the id before using it as a GenerationMatch precondition.","triggerScenarios":"Unlock(id) is called with a non-numeric string — e.g., a hand-typed lock ID, a UUID from a different backend, a corrupted env var, or an empty string.","commonSituations":"User passes the workspace name or a UUID to force-unlock instead of the numeric generation; CI script reads the wrong field from the lock file JSON; lock ID was truncated when copied.","solutions":["Re-read the lock info from the lock file and copy the numeric ID/generation exactly.","Run `terraform force-unlock` and let it read the ID from state rather than typing it.","Verify the lock file JSON's 'ID' field is the generation number."],"exampleFix":"// before\nterraform force-unlock tf-default\n// after — use the numeric generation from the lock file\nterraform force-unlock 1234567890","handlingStrategy":"validation","validationCode":"// Validate the lock ID is numeric before calling Unlock.\nif _, err := strconv.ParseInt(id, 10, 64); err != nil {\n    return fmt.Errorf(\"lock ID %q is not the numeric generation; copy ID from the lock file\", id)\n}","typeGuard":"func isNumericLockID(id string) bool {\n    _, err := strconv.ParseInt(id, 10, 64)\n    return err == nil\n}","tryCatchPattern":null,"preventionTips":["Let `terraform force-unlock` read the ID from state instead of typing it.","Always copy the 'ID' field from the lock file JSON verbatim.","Never substitute a UUID or workspace name for the GCS generation number."],"tags":["gcs","backend","state-locking","validation","recovery"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}