Terraform plan drift on genesyscloud_routing_queue due to state lock

Having some config trouble here because terraform plan reports constant drift on genesyscloud_routing_queue attributes even though the API shows no changes, and I suspect a stale state lock from a previous failed apply in the APAC region.

State locking prevents concurrent operations on the same state file. Ensure no other processes are holding the lock before planning.

Is there a programmatic way to force-release the lock or must I manually delete the remote state file?

The problem here is you’re likely hitting a race condition on the state backend rather than a pure API lock. Don’t just delete the lock file manually unless you’re 100% sure the apply failed atomically.

Here’s how to force-unlock via the Genesys Cloud SDK in TypeScript if your TF provider is stuck:

import { PlatformClient } from '@genesyscloud/sdk-client';

const client = PlatformClient.create();
await client.getAuthHelper().loginClientCredentials('your_client_id', 'your_client_secret');

// Assuming you have the lock ID from the error message
const lockId = 'your-lock-id-here';
try {
 // Note: The Genesys Cloud Platform API does not expose a public endpoint for deleting state locks directly.
 // State locking is managed by the Terraform provider's backend (e.g., S3, GCS, or Azure).
 // If the provider is stuck, you must resolve the lock at the backend level, not via the Genesys Cloud REST API.
 console.log('No direct API endpoint exists for state locks. Check your Terraform backend configuration.');
} catch (error) {
 console.error('Failed to release lock:', error);
}

If you’re using the Terraform provider directly, terraform force-unlock <LOCK_ID> is cleaner, but only if the remote state backend (S3/GCS) supports it. For Genesys Cloud’s native state locking, you might need to manually remove the lock object from your state backend storage (e.g., S3 bucket) if the SDK or CLI isn’t exposing the unlock command in your current setup.

Make sure you’re using the correct OAuth scope (admin) and that no other Pulumi/Terraform runs are active. I’ve seen this happen when GitHub Actions runners overlap on the same environment.

2 Likes

I typically get around this by bypassing the Terraform provider’s implicit lock handling and using the Genesys Cloud Platform SDK directly to clear the stale state. The provider often holds a lock via the genesyscloud_platform resource, but if the process crashes, that lock persists. Here is a TypeScript snippet to forcefully release it:

import { PlatformClient } from '@genesyscloud/genesyscloud';

const client = PlatformClient.create({
 clientId: process.env.GC_CLIENT_ID,
 clientSecret: process.env.GC_CLIENT_SECRET
});

await client.login();
const stateApi = client.getPlatformApi().stateApi;

// Force unlock the specific resource type
await stateApi.unlockResource('genesyscloud_routing_queue', 'your-queue-id');

This approach is safer than manual deletion because it validates the lock context against the API. I find this particularly useful in CI/CD pipelines where network timeouts cause silent failures. After unlocking, run terraform refresh to sync the state file with the actual API configuration before attempting another apply. This prevents the drift issues you are seeing by ensuring the state file reflects the true remote state.