NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Go modules, #2969 by repository stars
Latest stable
v1.20.0
Last release 8 days ago
06 Nov 2026
Release timing varies
gaps range from 8 days to 6 months
Nearly every release is documented
notes for 50 of 51 stable releases
Nothing withdrawn
no release was ever pulled
10 years old
286 releases · first in 2017
Drag across the ruler to compare, or tap a release to open it.
Nothing published for this version
This release introduces a new concept called provenance marks, which is a subcategory of marks that get more conservative treatment in how they are pr
This release introduces a new concept called provenance marks, which is a subcategory of marks that get more conservative treatment in how they are propagated through operations involving unknown values.
Alongside that, it's now possible for an unknown value to track both direct marks (as before) and an approximation of what marks could be nested inside a final known value in the same position. This means that for unknown values it's now possible for Value.UnmarkDeep to return a larger set of marks than Value.Unmark, just as for known collection and structural values. This is an approximation, though: it tracks only that a certain mark could potentially appear anywhere within the final object, not a specific path where it will appear. This is just enough complexity to preserve the presence of nested provenance marks, at the expense of being more conservative in how marks might propagate in subsequent operations.
The development of the functionality related to provenance marks was sponsored by Spacelift on behalf of the OpenTofu Project, which is intending to make more extensive use of marks to track dependencies by dynamic analysis instead of by simply searching for syntactic references to other objects. That mechanism relies on the assumption that an operation involving unknown values will produce an unknown result that has the superset of all possible dependency marks that could appear on a subsequent re-run of the same operation with known operands, which is what the more conservative treatment of provenance marks is intended to achieve.
Other smaller changes in this release:
cty.Value.GetAttrByValue is like cty.Value.GetAttr except that it takes the attribute name as cty.Value instead of string, and can therefore implement a reasonable reaction to the attribute name being unknown for calling applications that support dynamically-chosen attribute names.cty.Object, cty.ObjectVal, and cty.MapVal now all require the caller to ensure that no two attribute names or keys normalize to the same cty string, whereas before they all just nondeterministically selected any one of the conflicting attribute types. (#225)SignumFunc now works with any number cty can represent, whereas before it was unnecessarily limited only to numbers that could be converted to Go's int type. (#218)Your coding agent can read these notes before it upgrades. Set up the MCP server →
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
When building with Go 1.27 or later, the various string operations that are defined in terms of UAX#29 grapheme cluster segmentation will now use the
cty.ValueMarks type, which represents a set of value marks separately from any value, now has method Has for concisely testing if a specific mark is present, and Insert for inserting elements from an iter.Seq[any] into an existing set of marks for easier gradual construction without creating any temporary mark sets.stdlib: ContainsFunc now allows its second argument to be null, to test whether the given collection contains any null elements.
ContainsFunc now allows its second argument to be null, to test whether the given collection contains any null elements.MergeFunc no longer panics if all of its arguments are null values of the same object type with at least one attribute.Nothing published for this version
Nothing published for this version
Nothing published for this version
cty now requires Go 1.25 or later.
cty now requires Go 1.25 or later.
cty.Value.Equals now has a special case where if a null value is compared with a non-null value then only top-level marks from the non-null value will transfer to the boolean result.
This is a limited introduction of the idea that only the parts of a nested data structure that were actually relevant to the comparison should transfer to the result. The more general form of that idea might follow in a later release, but that would require some more severe refactoring of this method's implementation that would be far riskier and so this is a pragmatic compromise to support just the relatively-common case of comparing with null in callers like HCL where an equality test is the canonical way to test a value for "null-ness".
cty.IndexStep.Apply now works for traversing through a set.
Although cty.Value.Index does not allow looking up a set element due to set elements not having indices, we often use cty.Path to describe a specific location in a nested structure and have a convention of handling traversal through a set as a cty.IndexStep whose "key" is the set element's value.
To make that work a little better with code that uses cty.Path.Apply on such paths, cty.IndexStep now has a special case where if the given value is a set then it checks whether the index step's key is a member of the set and returns that value if so. If unknown values mean that it's not decidable whether there is a matching element then the result is an unknown value of the set's element type, so that traversal can continue and presumably eventually return an unknown value of the appropriate leaf type.
cty now requires Go 1.23 or later.
cty now requires Go 1.23 or later.
cty.Value.Elements offers a modern iter.Seq2-based equivalent of cty.Value.ElementIterator.
cty.DeepValues offers a modern iter.Seq2-based equivalent of cty.Walk.
cty.Value.WrangleMarksDeep allows inspecting and modifying individual marks throughout a possibly-nested data structure.
Having now got some experience using marks more extensively in some callers, it's become clear that it's often necessary for different subsystems to be able to collaborate using independent marks without upsetting each other's assumptions. Today that tends to be achieved using hand-written transforms either with cty.Transform or cty.Value.UnmarkDeepWithPaths/cty.Value.MarkWithPaths, both of which can be pretty expensive even in the common case where there are no marks present at all.
This new function allows inspecting and transforming marks with far less overhead, by creating new values only for parts of a structure that actually need to change and by reusing (rather than recreating) the "payloads" of the values being modified when we know that only the marks have changed.
cty.ValueMarksOfType and cty.ValueMarksOfTypeDeep make it easier to use type-based rather than value-based mark schemes, where different values of a common type are used to track a specific kind of relationship with multiple external values.
cty.Value.HasMarkDeep provides a "deep" version of the existing cty.Value.HasMark, searching throughout a possibly-nested structure for any values that have the given mark.
cty.Value.UnmarkDeep and cty.Value.UnmarkDeepWithPaths are now implemented in terms of cty.Value.WrangleMarksDeep, so they benefit from its reduced overhead. In particular they avoid reconstructing a data structure that contains no marked values at all.
cty.Value.MarkWithPaths now has a fast path when it's given a zero-length PathValueMarks, in which case it just returns the value it was given with no modifications.
Nothing published for this version
Nothing published for this version
Nothing published for this version
cty.UnknownAsNull now accepts marked values and preserves the given marks in its result. Previously it had no direct support for marks and so would ei
cty.UnknownAsNull now accepts marked values and preserves the given marks in its result. Previously it had no direct support for marks and so would either panic or return incorrect results when given marked values.Nothing published for this version
Nothing published for this version
convert: Now generates more specific error messages in various cases of type conversion failure, giving additional information about the type that was
convert: Now generates more specific error messages in various cases of type conversion failure, giving additional information about the type that was given as compared to the type that was wanted by the caller.Nothing published for this version
json: ImpliedType now returns an error if a JSON object contains two properties of the same name. As a compatibility concession it allows duplicates w
json: ImpliedType now returns an error if a JSON object contains two properties of the same name. As a compatibility concession it allows duplicates whose values have the same implied type, since it was unintentionally possible to combine ImpliedType and Unmarshal successfully in that case before, but this is not an endorsement of using duplicate property names since that makes the input ambiguous in any case. (#199)function/stdlib: ElementFunc no longer crashes when asked for a negative index into a tuple. This fixes a miss in the negative index support added back in v1.15.0. (#200)Nothing published for this version
Nothing published for this version
cty: Value.HasElement now treats unknown set elements consistently with how much of the rest of cty treats them.
cty: Value.HasElement now treats unknown set elements consistently with how much of the rest of cty treats them.function/stdlib: FormatFunc and FormatListFunc now handle unknown and null values of unknown type as arguments, rather than letting the function system's short-circuit behavior take care of it. This allows cty.DynamicVal and cty.NullVal(cty.DynamicPseudoType) to be treated consistently with other values, returning results consistent with the documented behavior, rather than forcing the function to immediately return cty.DynamicVal.Nothing published for this version
Nothing published for this version
convert : When converting between two different capsule types, will now try to use the "conversion from " implementation from the target type if the s
convert: When converting between two different capsule types, will now try to use the "conversion from" implementation from the target type if the source type doesn't have a suitable "conversion to" implementation. (#194)convert: When converting to a map whose element type is an object type with optional attributes, will no longer construct a broken result when a final map is empty. (#198)Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
function: Function calls can now return more mark-related information when called with unknown values when neither AllowMarks nor AllowUnknown are set
function: Function calls can now return more mark-related information when called with unknown values when neither AllowMarks nor AllowUnknown are set for a particular parameter. (#196)Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
function/stdlib: The element function now accepts negative indices, extending the illusion of an infinitely-long list into the negative direction too.
function/stdlib: The element function now accepts negative indices, extending the illusion of an infinitely-long list into the negative direction too.cty: The various "transform" functions were previously incorrectly propagating marks from a parent object down to attribute values when calling the caller-provided transform functions. The marks will now no longer be propagated downwards, which is consistent with the treatment of collection and tuple elements. If your transform function needs to take into account context about marks of upstream containers then you can maintain a stack of active marks in your Transformer implementation, pushing in Enter and popping in Exit. (#185)Nothing published for this version
Nothing published for this version
msgpack: Now uses string encoding instead of float encoding for a whole number that is too large to fit in any of MessagePack's integer types.
msgpack: Now uses string encoding instead of float encoding for a whole number that is too large to fit in any of MessagePack's integer types.function/stdlib: Type conversion functions (constructed with MakeToFunc) can now convert null values of unknown type into null values of the target type, rather than returning an unknown value in that case.json: Will now correctly reject attempts to encode cty.DynamicVal, whereas before it would just produce an invalid JSON document without any error. (This is invalid because JSON encoding cannot support unknown values at all; cty.DynamicVal is a special case of unknown value where even the type isn't known.)Nothing published for this version
Nothing published for this version
Nothing published for this version
msgpack: Fixed edge-case bug that could cause loss of floating point precision when round-tripping due to incorrectly using a MessagePack integer to r
msgpack: Fixed edge-case bug that could cause loss of floating point precision when round-tripping due to incorrectly using a MessagePack integer to represent a large non-integral number. #176cty: Fixed some false-negative numeric equality test results by comparing numbers as integers when possible. #176Nothing published for this version
Nothing published for this version
Nothing published for this version
convert: Converting from an unknown map value to an object type now correctly handles the situation where the map element type disagrees with an _opti
convert: Converting from an unknown map value to an object type now correctly handles the situation where the map element type disagrees with an optional attribute of the target type, since when a map value is unknown we don't yet know which keys it has and thus cannot predict what subset of the elements will get converted as attributes in the resulting object. (#175)Nothing published for this version
Nothing published for this version
cty: It's now valid to use the Refine method on cty.DynamicVal, although all refinements will be silently discarded. This replaces the original behavi
cty: It's now valid to use the Refine method on cty.DynamicVal, although all refinements will be silently discarded. This replaces the original behavior of panicking when trying to refine cty.DynamicVal.
cty: Value.Range will now return a clearer panic message if called on a marked value. The "value range" concept is only applicable to unmarked values because not all of the ValueRange functions are able to propagate marks into their return values, due to returning Go primitive types instead of new cty.Value results.
Callers that use marks must, as usual, take care to unmark them before exporting values into "normal" Go types, and then explicitly re-apply the marks to their result as appropriate. Applications that make no use of value marks, and library callers that exclude marked values from what they support, can safely ignore this requirement.
Nothing published for this version
Nothing published for this version
This release updates the supported version of Unicode from Unicode 13 to Unicode 15. This is a backwards-compatible change that means that cty support
This release updates the supported version of Unicode from Unicode 13 to Unicode 15. This is a backwards-compatible change that means that cty supports normalization and segmentation of strings containing new Unicode characters. The algorithms for normalization and segmentation themselves are unchanged.
If you use cty in an application that cares about consistent Unicode support, you should upgrade to Go 1.21 at the same time as updating to cty v1.14, because that will then also update the Unicode tables embedded in the Go standard library (used for case folding, etc).
cty: The cty.String type will now normalize incoming string values using the Unicode 15 normalization rules.function/stdlib: The various string functions which split strings into individual characters as part of their work will now use the Unicode 15 version of the text segmentation algorithm to do so.Nothing published for this version
One column per quarter.