These are intended to make it easier to work with arbitrary data
structures whose shape might not be known statically, such as the result
of jsondecode(...) or yamldecode(...) of data from a separate system.
For example, in an object value which has attributes that may or may not
be set we can concisely provide a fallback value to use when the attribute
isn't set:
try(local.example.foo, "fallback-foo")
Using a "try to evaluate" model rather than explicit testing fits better
with the usual programming model of the Terraform language where values
are normally automatically converted to the necessary type where possible:
the given expression is subject to all of the same normal type conversions,
which avoids inadvertently creating a more restrictive evaluation model
as might happen if this were handled using checks like a hypothetical
isobject(...) function, etc.
4.1 KiB
layout, page_title, sidebar_current, description
| layout | page_title | sidebar_current | description |
|---|---|---|---|
| functions | try - Functions - Configuration Language | docs-funcs-conversion-try | The try function tries to evaluate a sequence of expressions given as arguments and returns the result of the first one that does not produce any errors. |
try Function
-> Note: This page is about Terraform 0.12 and later. For Terraform 0.11 and earlier, see 0.11 Configuration Language: Interpolation Syntax.
try evaluates all of its argument expressions in turn and returns the result
of the first one that does not produce any errors.
This is a special function that is able to catch errors produced when evaluating its arguments, which is particularly useful when working with complex data structures whose shape is not well-known at implementation time.
For example, if some data is retrieved from an external system in JSON or YAML
format and then decoded, the result may have attributes that are not guaranteed
to be set. We can use try to produce a normalized data structure which has
a predictable type that can therefore be used more conveniently elsewhere in
the configuration:
locals {
raw_value = yamldecode("${path.module}/example.yaml")
normalized_value = {
name = tostring(try(local.raw_value.name, null))
groups = try(local.raw_value.groups, [])
}
}
With the above local value expressions, configuration elsewhere in the module
can refer to local.normalized_value attributes without the need to repeatedly
check for and handle absent attributes that would otherwise produce errors.
We can also use try to deal with situations where a value might be provided
in two different forms, allowing us to normalize to the most general form:
variable "example" {
type = any
}
locals {
example = try(
[tostring(var.example)],
tolist(var.example),
)
}
The above permits var.example to be either a list or a single string. If it's
a single string then it'll be normalized to a single-element list containing
that string, again allowing expressions elsewhere in the configuration to just
assume that local.example is always a list.
This second example contains two expressions that can both potentially fail.
For example, if var.example were set to {} then it could be converted to
neither a string nor a list. If try exhausts all of the given expressions
without any succeeding, it will return an error describing all of the problems
it encountered.
We strongly suggest using try only in special local values whose expressions
perform normalization, so that the error handling is confined to a single
location in the module and the rest of the module can just use straightforward
references to the normalized structure and thus be more readable for future
maintainers.
The try function can only catch and handle dynamic errors resulting from
access to data that isn't known until runtime. It will not catch errors
relating to expressions that can be proven to be invalid for any input, such
as a malformed resource reference.
~> Warning: The try function is intended only for concise testing of the
presence of and types of object attributes. Although it can technically accept
any sort of expression, we recommend using it only with simple attribute
references and type conversion functions as shown in the examples above.
Overuse of try to suppress errors will lead to a configuration that is hard
to understand and maintain.
Examples
> local.foo
{
"bar" = "baz"
}
> try(local.foo.bar, "fallback")
baz
> try(local.foo.boop, "fallback")
fallback
The try function will not catch errors relating to constructs that are
provably invalid even before dynamic expression evaluation, such as a malformed
reference or a reference to a top-level object that has not been declared:
> try(local.nonexist, "fallback")
Error: Reference to undeclared local value
A local value with the name "nonexist" has not been declared.
Related Functions
can, which tries evaluating an expression and returns a boolean value indicating whether it succeeded.