ARM Template Functions
Expert knowledge for using Azure Resource Manager (ARM) template functions, especially reference(), listKeys(), and resourceId() in subscription-level and nested deployments. Use when working with ARM templates, encountering template validation errors, or implementing cross-scope resource references.
Best use case
ARM Template Functions is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Expert knowledge for using Azure Resource Manager (ARM) template functions, especially reference(), listKeys(), and resourceId() in subscription-level and nested deployments. Use when working with ARM templates, encountering template validation errors, or implementing cross-scope resource references.
Teams using ARM Template Functions should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/arm-template-functions/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How ARM Template Functions Compares
| Feature / Agent | ARM Template Functions | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Expert knowledge for using Azure Resource Manager (ARM) template functions, especially reference(), listKeys(), and resourceId() in subscription-level and nested deployments. Use when working with ARM templates, encountering template validation errors, or implementing cross-scope resource references.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# ARM Template Functions Skill
## When to Use This Skill
- Working with Azure ARM templates (azuredeploy.json files)
- Encountering template validation errors related to functions
- Implementing subscription-level deployments
- Using nested deployments with cross-scope references
- Accessing resource properties in outputs sections
## Critical Rules for ARM Template Functions
### reference() Function
**Valid Usage Locations:**
- ✅ Outputs section
- ✅ Properties object of resource definitions
- ❌ Top-level resource properties (type, name, location)
- ❌ Count property in copy loops
**Scope Considerations:**
```json
// ✅ CORRECT: Simple reference in same scope
"outputs": {
"myOutput": {
"value": "[reference('myResourceName').someProperty]"
}
}
// ❌ INCORRECT: Cannot nest reference() inside other functions in outputs
"outputs": {
"myOutput": {
"value": "[listKeys(resourceId('rg', 'type', reference('dep').outputs.name.value))]"
}
}
```
**Nested Deployment References:**
- Use `reference(deploymentName).outputs.propertyName.value` for outputs
- Requires `expressionEvaluationOptions.scope: inner` in nested deployment
- Cannot use `reference()` inside `resourceId()` or `listKeys()` in outputs
**Conditional Deployment Warning:**
- `reference()` evaluates even if resource is conditionally not deployed
- This can cause deployment failures
- Always ensure referenced resources exist
### listKeys() Function
**Requirements:**
- Can only be used in outputs section or resource properties
- Requires fully qualified resource ID
- Resource must exist before evaluation
- Requires correct API version
**Valid Pattern:**
```json
"outputs": {
"storageKey": {
"value": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('name')), '2023-01-01').keys[0].value]"
}
}
```
**Security Warning:**
- Never expose sensitive list functions (listKeys, listSecrets) in outputs
- Output values are stored in deployment history
- Anyone with read access to deployment can see outputs
### resourceId() Function Scope Variations
**Resource Group Scope (default):**
```json
"[resourceId('Microsoft.Storage/storageAccounts', parameters('name'))]"
// Returns: /subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Storage/storageAccounts/{name}
```
**Cross-Resource Group:**
```json
"[resourceId(parameters('resourceGroupName'), 'Microsoft.Storage/storageAccounts', parameters('name'))]"
```
**Subscription Scope:**
```json
"[subscriptionResourceId('Microsoft.EventHub/namespaces', parameters('name'))]"
// Returns: /subscriptions/{sub}/providers/Microsoft.EventHub/namespaces/{name}
```
**⚠️ CRITICAL: Cross-Scope from Subscription Template to Resource Group Resources**
When in a **subscription-level template** referencing resources IN a resource group:
```json
// ❌ WRONG - Will fail with "not valid subscription identifier"
"[resourceId(parameters('resourceGroupName'), 'Microsoft.Storage/storageAccounts', parameters('name'))]"
// ✅ CORRECT - Must include subscription ID
"[resourceId(subscription().subscriptionId, parameters('resourceGroupName'), 'Microsoft.Storage/storageAccounts', parameters('name'))]"
```
This applies to:
- listKeys() calls
- Any resourceId() in outputs or properties
- Diagnostic settings eventHubAuthorizationRuleId
**Management Group/Tenant:**
```json
"[tenantResourceId('Microsoft.Authorization/policyDefinitions', parameters('name'))]"
```
**⚠️ Critical:** In subscription-level templates, use `subscriptionResourceId()` NOT `resourceId()` for subscription-scoped resources.
## Common Errors and Solutions
### Error: "The template function 'reference' is not expected at this location"
**Cause:** Using `reference()` inside another function in outputs section
**Solution:** Store the referenced value in variables, or restructure to avoid nested reference calls:
```json
// ❌ INCORRECT
"outputs": {
"connectionString": {
"value": "[listKeys(resourceId('rg', 'type', reference('deployment').outputs.name.value))]"
}
}
// ✅ CORRECT: Use parameters or variables for the name
"outputs": {
"connectionString": {
"value": "[listKeys(resourceId(parameters('resourceGroupName'), 'Microsoft.EventHub/namespaces/eventhubs/authorizationRules', parameters('namespace'), parameters('hub'), parameters('ruleName')), '2022-10-01-preview').primaryConnectionString]"
}
}
// ✅ ALTERNATIVE: Use nested deployment outputs for simple values only
"outputs": {
"simpleName": {
"value": "[reference('deploymentName').outputs.nameOutput.value]"
}
}
```
### Error: "The content for this response was already consumed"
**Cause:** Azure CLI bug in versions 2.74.0 and earlier with subscription-level template validation
**Solution:**
```bash
# Update Azure CLI
brew upgrade azure-cli # macOS
# or
apt-get update && apt-get upgrade azure-cli # Linux
```
### Error: Resource not found in outputs
**Cause:** Incorrect scope function or missing resource group parameter
**Solution:** Match the scope function to deployment level:
- Resource group deployment → `resourceId()`
- Subscription deployment → `subscriptionResourceId()` or `resourceId(resourceGroupName, ...)`
- Management group deployment → `managementGroupResourceId()`
## Best Practices for Nested Deployments
### Subscription-Level Template with Resource Group Nested Deployment
```json
{
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
"resources": [
{
"type": "Microsoft.Resources/deployments",
"name": "nestedDeployment",
"resourceGroup": "[parameters('resourceGroupName')]",
"properties": {
"mode": "Incremental",
"expressionEvaluationOptions": {
"scope": "inner" // Critical for reference() in nested outputs
},
"template": {
// Inner template deploys to resource group
"outputs": {
"resourceName": {
"value": "[parameters('name')]" // Simple values work
}
}
}
}
}
],
"outputs": {
// Access nested outputs
"name": {
"value": "[reference('nestedDeployment').outputs.resourceName.value]"
},
// Use outputs in other functions - pass as parameters, not nested reference
"connectionString": {
"value": "[listKeys(resourceId(parameters('resourceGroupName'), 'Microsoft.Storage/storageAccounts', parameters('storageName')), '2023-01-01').keys[0].value]"
}
}
}
```
### Key Pattern: Avoid Nested Function Calls
**The Golden Rule:** In outputs, DO NOT nest `reference()` inside `listKeys()` or `resourceId()`.
**Instead:**
1. Pass resource names as parameters
2. Store complex expressions in variables (where allowed)
3. Use nested deployment outputs only for simple string/number values
4. Build resource IDs with parameters, not with reference() results
## Validation Commands
```bash
# Validate subscription-level template
az deployment sub validate \
--location eastus \
--template-file azuredeploy.json \
--parameters @parameters.json
# Validate resource group template
az deployment group validate \
--resource-group myResourceGroup \
--template-file azuredeploy.json \
--parameters @parameters.json
# What-if preview (subscription level)
az deployment sub what-if \
--location eastus \
--template-file azuredeploy.json \
--parameters @parameters.json
```
## Additional Resources
- [ARM Template Functions Reference](https://learn.microsoft.com/azure/azure-resource-manager/templates/template-functions)
- [Resource Functions](https://learn.microsoft.com/azure/azure-resource-manager/templates/template-functions-resource)
- [Deployment Scopes](https://learn.microsoft.com/azure/azure-resource-manager/templates/deploy-to-subscription)Related Skills
documentation-templates
Documentation templates and structure guidelines. README, API docs, code comments, and AI-friendly documentation.
acc-troubleshooting-template
Generates troubleshooting guides and FAQ sections for PHP projects. Creates problem-solution documentation.
acc-readme-template
Generates README.md files for PHP projects. Creates structured documentation with badges, installation, usage, and examples.
acc-getting-started-template
Generates Getting Started guides for PHP projects. Creates step-by-step tutorials for first-time users.
acc-code-examples-template
Generates code examples for PHP documentation. Creates minimal, copy-paste ready examples with expected output.
acc-changelog-template
Generates CHANGELOG.md files following Keep a Changelog format. Creates version history documentation.
github-actions-templates
Create production-ready GitHub Actions workflows for automated testing, building, and deploying applications. Use when setting up CI/CD with GitHub Actions, automating development workflows, or creating reusable workflow templates.
employment-contract-templates
Create employment contracts, offer letters, and HR policy documents following legal best practices. Use when drafting employment agreements, creating HR policies, or standardizing employment docume...
cloud-functions
Complete guide for CloudBase cloud functions development - runtime selection, deployment, logging, invocation, and HTTP access configuration.
templates
Project scaffolding templates for new applications. Use when creating new projects from scratch. Contains 12 templates for various tech stacks.
svelte-remote-functions
Guide for SvelteKit Remote Functions. Use this skill by default for all SvelteKit projects doing type-safe client-server communication with query (data fetching), form (progressive enhancement), command (imperative actions), or data invalidation/refresh patterns.
setup-cdk-templates
Use when creating CLAUDE.md files or .claude/ directories - detects project type, generates appropriate templates, and scaffolds Claude configuration with commands and hooks