Description
resourceGithubCustomPropertiesRead in resource_github_organization_custom_properties.go propagates any error from client.Organizations.GetCustomProperty verbatim, without checking for a 404 (not found) response:
func resourceGithubCustomPropertiesRead(d *schema.ResourceData, meta any) error {
ctx := context.Background()
client := meta.(*Owner).v3client
ownerName := meta.(*Owner).name
customProperty, _, err := client.Organizations.GetCustomProperty(ctx, ownerName, d.Get("property_name").(string))
if err != nil {
return err // <-- no 404 handling; should clear state (d.SetId("")) and return nil
}
...
}
This violates the standard Terraform provider idiom: when Read gets a 404 for a resource that no longer exists (e.g., because it was deleted out-of-band, or because a prior Delete succeeded but something is re-verifying), it should call d.SetId("") and return nil, signaling "no longer exists" rather than a hard error. The closely related repo-scoped sibling, resource_github_repository_custom_property.go, correctly does:
if err, ok := errors.AsType[*github.ErrorResponse](err); ok && err.Response.StatusCode == 404 {
// clears state
}
Impact
Any tool that relies on this resource's Read returning a clean "not found" for a deleted github_organization_custom_properties resource gets stuck: after a successful Delete, the next Read/refresh gets a 404 from GitHub (correctly, since the delete succeeded), but the 404 is returned as an error instead of "resource gone."
Steps to reproduce
terraform import or create a github_organization_custom_properties resource.
- Delete the underlying property directly via the GitHub API (or via
terraform destroy, then attempt a subsequent plan/refresh).
- Observe that
Read returns a hard error (404 Not Found) instead of clearing resource state.
Expected behavior
Read should detect a 404 from GetCustomProperty and call d.SetId(""), returning nil, consistent with resource_github_repository_custom_property.go's handling.
Suggested fix
customProperty, resp, err := client.Organizations.GetCustomProperty(ctx, ownerName, d.Get("property_name").(string))
if err != nil {
if resp != nil && resp.StatusCode == http.StatusNotFound {
d.SetId("")
return nil
}
return err
}
Environment
terraform-provider-github v6.13.0
Description
resourceGithubCustomPropertiesReadinresource_github_organization_custom_properties.gopropagates any error fromclient.Organizations.GetCustomPropertyverbatim, without checking for a 404 (not found) response:This violates the standard Terraform provider idiom: when
Readgets a 404 for a resource that no longer exists (e.g., because it was deleted out-of-band, or because a priorDeletesucceeded but something is re-verifying), it should calld.SetId("")and returnnil, signaling "no longer exists" rather than a hard error. The closely related repo-scoped sibling,resource_github_repository_custom_property.go, correctly does:Impact
Any tool that relies on this resource's Read returning a clean "not found" for a deleted
github_organization_custom_propertiesresource gets stuck: after a successfulDelete, the nextRead/refresh gets a 404 from GitHub (correctly, since the delete succeeded), but the 404 is returned as an error instead of "resource gone."Steps to reproduce
terraform importor create agithub_organization_custom_propertiesresource.terraform destroy, then attempt a subsequent plan/refresh).Readreturns a hard error (404 Not Found) instead of clearing resource state.Expected behavior
Readshould detect a 404 fromGetCustomPropertyand calld.SetId(""), returningnil, consistent withresource_github_repository_custom_property.go's handling.Suggested fix
Environment
terraform-provider-githubv6.13.0