Repository: opentofu/opentofu
File: internal/configs/resource.go (Go)

Code before:
	if r.Alias != "" {
		return fmt.Sprintf("%s.%s", r.Name, r.Alias)
	}
	return r.Name
}

func (r *ProviderConfigRef) InstanceValidation(blockType string, isInstanced bool, hasConfig bool) hcl.Diagnostics {
	var diags hcl.Diagnostics

	summary := fmt.Sprintf("Invalid %s provider configuration", blockType)

	if r.KeyExpression != nil {
		if r.Alias == "" {
			diags = append(diags, &hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  summary,
				Detail:   "An instance key can be specified only for a provider configuration which has an alias and uses for_each.",
				Subject:  r.KeyExpression.Range().Ptr(),
			})
		}
		if !isInstanced {
			if !hasConfig {
				diags = append(diags, &hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  summary,
					Detail:   fmt.Sprintf("An instance key can only be used with a provider configured with for_each. No provider configuration was detected for %q", r.String()),
					Subject:  r.KeyExpression.Range().Ptr(),
				})
			} else {
				diags = append(diags, &hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  summary,
					Detail:   "An instance key can be specified only for a provider configuration that uses for_each.",
					Subject:  r.KeyExpression.Range().Ptr(),
				})

			}
		}
	} else if isInstanced {
		diags = append(diags, &hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  summary,
			Detail:   "A reference to a provider configuration which uses for_each requires an instance key. Passing a collection of provider instances into a child module is not allowed.",
			Subject:  r.NameRange.Ptr(),
		})
	}
	return diags
}

var commonResourceAttributes = []hcl.AttributeSchema{
	{

Review comment (bug):
```suggestion
					Detail:   fmt.Sprintf("This module doesn't declare a provider %q block with alias = %q.", r.Name, r.Alias),
```

In this specific situation I think it's helpful to focus on the direct problem we detected -- that there's no matching provider configuration block -- and to not mention the `for_each`-specific situation at all because that's secondary to the problem and I think therefore makes it less clear what the author should do to fix this error.

If they then end up adding a new block _without_ `for_each` in it then they'll see the error from the other branch of this `if` statement soon enough, but I suspect the more likely case is that there _is_ already a block but the reference to it has been typed incorrectly, as in the issue we're responding to here. So in that case we'd say:

> This module doesn't declare a provider "postgres" block with alias = "by_db".

...which hopefully prompts the reader to notice that what they _actually_ have is a `provider "postgresql"` block, correct the reference to be `postgresql.by_db[each.key]` instead, and then everything is fine.

Along with that suggestion, I think we should make sure we can't get in here in the situation where `r.Alias == ""` both because my error message suggestion above assumes that `r.Alias` is set here and because I think it's confusing to report two different diagnoses of the same problem. Perhaps we can change the `if !isInstanced` statement to be an `else if` from the `r.Alias == ""` check, so that we're always either reporting that the reference is to an _unsuitable_ block or that the reference is to a _missing_ block, but never both at the same time.



Code after:
	if r.Alias != "" {
		return fmt.Sprintf("%s.%s", r.Name, r.Alias)
	}
	return r.Name
}

func (r *ProviderConfigRef) InstanceValidation(blockType string, isInstanced bool, hasConfig bool) hcl.Diagnostics {
	var diags hcl.Diagnostics

	summary := fmt.Sprintf("Invalid %s provider configuration", blockType)

	if r.KeyExpression != nil {
		if r.Alias == "" {
			diags = append(diags, &hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  summary,
				Detail:   "An instance key can be specified only for a provider configuration which has an alias and uses for_each.",
				Subject:  r.KeyExpression.Range().Ptr(),
			})
		} else if !isInstanced {
			if !hasConfig {
				diags = append(diags, &hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  summary,
					Detail:   fmt.Sprintf("This module doesn't declare a provider %q block with alias = %q, which is required for use with for_each.", r.Name, r.Alias),
					Subject:  r.NameRange.Ptr(),
				})
			} else {
				diags = append(diags, &hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  summary,
					Detail:   "An instance key can be specified only for a provider configuration that uses for_each.",
					Subject:  r.KeyExpression.Range().Ptr(),
				})

			}
		}
	} else if isInstanced {
		diags = append(diags, &hcl.Diagnostic{
			Severity: hcl.DiagError,
			Summary:  summary,
			Detail:   "A reference to a provider configuration which uses for_each requires an instance key. Passing a collection of provider instances into a child module is not allowed.",
			Subject:  r.NameRange.Ptr(),
		})
	}
	return diags
}

var commonResourceAttributes = []hcl.AttributeSchema{
	{
		Name: "count",