Skip to content

HCL blocks vs kv maps is fragile #2596

Open

Description

@philpennock

Describe the bug
Trying to construct HCL which uses blocks, the output of yq in HCL mode is fragile as to whether the input strings contain certain characters.

Two input files, moved-simple.tf and moved-modules.tf

moved-simple.tf:

moved {
  from = "OLD"
  to   = "NEW"
}

moved-modules.tf:

moved {
  from = "module[\"OLD\"].foo"
  to   = "module[\"NEW\"].foo"
}

Using a command of yq -phcl -ojson | yq -pjson -ohcl to check round-tripping, we see some issues.

% yq < moved-simple.tf -phcl -ojson | yq -pjson -ohcl
moved {
  from = OLD
  to = NEW
}

% yq < moved-modules.tf -phcl -ojson | yq -pjson -ohcl
moved {
}
moved = {
  from = "module[\"OLD\"].foo"
  to = "module[\"NEW\"].foo"
}

You can see that in the simple case, we get a block output and round-trip fine. In the case which differs only in the string content of the data input, we no longer round-trip fine, and get both a block (empty) and a key/value assignment of an object.


Version of yq: v4.52.2
Operating system: linux
Installed via: go install

Additional context
Add any other context about the problem here.

I constructed some moved blocks from a terraform state pull, using xargs and shell echo. I had hoped to avoid the fragile shell and use yq instead but can't figure out how we signal when input is supposed to be block vs object assignment and can't make it reliable in the presence of the sort of strings encountered in a terraform state file.

Activity

  1. phene commented on Feb 26, 2026

    @phene

    Yeah, blocks vs kv maps are problematic

    foo.tf:

    module "route53_dnssec_kms" {
      description = "KMS for DNSSEC"
      source      = "terraform-aws-modules/kms/aws"
      some_attr   = var.foo
      version     = "4.0.0"
    }
    
    variable "foo" {
      type = string
    }
    
    variable "bar" {
      type = string
    }
    

    yq -phcl -oyml foo.tf | yq -pyml -ohcl

    module "route53_dnssec_kms" {
      description = "KMS for DNSSEC"
      source = "terraform-aws-modules/kms/aws"
      some_attr = var.foo
      version = "4.0.0"
    }
    variable {
      foo {
        type = string
      }
      bar {
        type = string
      }
    }
    

    And conversion to JSON runs into this issue

    IMO, It may not be possible to reliably convert between HCL and other types unless you define a very arbitrary format. See hcl2json for another attempt to convert HCL to a JSON format, but I think it would also struggle with conversion back to HCL

    Version of yq: v4.52.4
    Operating system: osx
    Installed via: homebrew

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions