What's Actually Happening
OPA Rego policy file has syntax errors. Policy cannot be parsed or loaded by OPA.
The Error You'll See
```bash $ opa check policy.rego
policy.rego:5: rego_parse_error: unexpected identifier token: if ```
Missing package:
policy.rego:1: rego_parse_error: package declaration requiredInvalid rule syntax:
policy.rego:10: rego_parse_error: rule head must be identifier or referenceOperator error:
policy.rego:15: rego_parse_error: invalid comparison operatorWhy This Happens
- 1.Missing package - No package declaration at file start
- 2.Invalid keywords - Wrong keyword usage (if, else, some)
- 3.Brace errors - Missing or mismatched braces
- 4.Operator errors - Invalid comparison or arithmetic operators
- 5.Comment syntax - Wrong comment format
- 6.Import issues - Missing or invalid imports
Step 1: Add Package Declaration
```rego # Every Rego file must start with package declaration:
# BAD: allow { input.role == "admin" }
# GOOD: package policy
allow if { input.role == "admin" }
# Package name format: package auth.policy # Nested package package myapp # Simple package
# Package must be first non-comment line: # File: auth.rego package auth
allow if { input.user == "admin" }
# Then evaluate: opa eval -d auth.rego 'data.auth.allow' ```
Step 2: Fix Rule Syntax
```rego # Rego v1 syntax (recommended):
# Rule with if: allow if { input.role == "admin" }
# Rule without body (constant): default allow := false
# Partial rule set: roles contains "admin" if { input.is_admin }
# Rule with value: message := "Access granted" if { allow }
# OLD syntax (deprecated but works): # allow { # input.role == "admin" # }
# Rule head must be identifier: # BAD: 123_allow if { ... } # Starts with number # GOOD: allow_123 if { ... }
# Rule with arguments: is_admin(user) if { user.role == "admin" } ```
Step 3: Fix Braces and Structure
```rego # Rego uses braces for rule bodies and sets:
# Rule body braces: allow if { input.role == "admin" # Condition input.active == true # Another condition } # All conditions must be true for rule to be true
# Set braces (values): roles := {"admin", "user", "guest"}
# Object braces (key-value pairs): config := { "host": "localhost", "port": 8080 }
# Comprehension braces: admin_users := { user | some user in input.users user.role == "admin" }
# Missing braces error: # BAD: allow if input.role == "admin" # Missing braces!
# GOOD: allow if { input.role == "admin" }
# Mismatched braces: # BAD: allow if { input.role == "admin" } } # Extra brace
# GOOD: allow if { input.role == "admin" } ```
Step 4: Fix Comparison Operators
```rego # Valid comparison operators:
# Equality: input.role == "admin" input.id != 100
# Comparison: input.age > 18 input.age >= 18 input.age < 65 input.age <= 65
# Invalid operators: # BAD: input.role = "admin" # Single = is assignment, not comparison input.role === "admin" # Not valid in Rego input.role <> "admin" # Not valid in Rego
# GOOD: input.role == "admin"
# Assignment operator: x := 5 y = input.value # Also valid for assignment
# Logical operators: allow if { input.role == "admin" input.active == true # AND (implicit) }
allow if { input.role == "admin" } else if { input.role == "user" # OR (else if) }
# Or operator: allow if { input.role == "admin" or input.role == "superuser" } ```
Step 5: Fix Iteration Syntax
```rego # Rego v1 iteration with some:
# Iterate array: some user in input.users user.role == "admin"
# Iterate with index: some i, user in input.users user.role == "admin" i < 10
# Iterate object: some key, value in input.config key == "host"
# OLD syntax (deprecated): # user := input.users[_] # user.role == "admin"
# Comprehension iteration: admin_users := { user.name | some user in input.users user.role == "admin" }
# Array comprehension: admin_names := [ user.name | some user in input.users user.role == "admin" ]
# Invalid iteration: # BAD: for user in input.users { # No for loop in Rego! user.role == "admin" }
# GOOD: some user in input.users user.role == "admin" ```
Step 6: Fix Comments
```rego # Comments in Rego:
# Line comment (starts with #): # This is a comment allow if { input.role == "admin" # Inline comment }
# Block comments (multiple #): # This is a # multi-line # comment
# Invalid comment: # BAD: // Not a comment! // syntax not valid /* Not valid */ # /* */ syntax not valid
# GOOD: # Use # for all comments
# Comment at end of line: allow if { input.role == "admin" # Check role }
# Document rules with comments: # Allow access if user is admin # and account is active allow if { input.role == "admin" input.active == true } ```
Step 7: Fix Import Statements
```rego # Import statements:
# Import built-in functions: import future.keywords.if import future.keywords.contains
# With imports, use new syntax: package policy
import future.keywords.if
allow if { input.role == "admin" }
# Import external data: import data.users
allow if { some user in users user.name == input.user user.role == "admin" }
# Invalid import: # BAD: import "future.keywords.if" # Not a string
# GOOD: import future.keywords.if
# Import from other package: import data.auth.users ```
Step 8: Fix Functions
```rego # Functions in Rego:
# Function definition: is_admin(user) if { user.role == "admin" }
# Function call: allow if { is_admin(input.user) }
# Function with return value: get_role(user) := user.role
# Use return value: role := get_role(input.user)
# Function with multiple args: has_permission(user, action) if { some perm in user.permissions perm == action }
# Invalid function: # BAD: function is_admin(user) { # No function keyword return user.role == "admin" }
# GOOD: is_admin(user) if { user.role == "admin" } ```
Step 9: Fix Else Statements
```rego # Else statements:
# Simple else: allow if { input.role == "admin" } else if { input.role == "user" input.action == "read" } else { false # Deny everyone else }
# Else with value: message := "Admin access" if { input.role == "admin" } else := "User access" if { input.role == "user" } else := "Access denied"
# Invalid else: # BAD: allow if { input.role == "admin" } else { # else on new line without brace false }
# GOOD: allow if { input.role == "admin" } else { false }
# else must follow } immediately: allow if { ... } else if { ... } else { ... } ```
Step 10: Rego Syntax Verification Script
```bash # Create verification script: cat << 'EOF' > /usr/local/bin/check-rego-syntax.sh #!/bin/bash
POLICY=${1:-"policy.rego"}
echo "=== Check Syntax ===" opa check $POLICY 2>&1
echo "" echo "=== Parse Tree ===" opa parse $POLICY 2>&1 | head -30
echo "" echo "=== Package Declaration ===" head -1 $POLICY
echo "" echo "=== Imports ===" grep "^import" $POLICY || echo "No imports"
echo "" echo "=== Rules Defined ===" grep -E "^[a-z_]+( if| :=| contains)" $POLICY || grep -E "^[a-z_]+\s*{" $POLICY
echo "" echo "=== Comments Check ===" grep -E "^(//|/*)" $POLICY && echo "WARNING: Invalid comment syntax" || echo "Comments OK"
echo "" echo "=== Operators Check ===" grep -E "(===|<>|= )" $POLICY && echo "WARNING: Invalid operators" || echo "Operators OK"
echo "" echo "=== Test Run ===" opa test $POLICY -v 2>&1 | tail -10
echo "" echo "=== Recommendations ===" echo "1. Add package declaration at file start" echo "2. Use == for comparison (not = or ===)" echo "3. Use # for comments (not // or /* */)" echo "4. Ensure braces {} are matched" echo "5. Use some for iteration (not for) echo "6. Add imports for new keywords" echo "7. Write tests for validation" EOF
chmod +x /usr/local/bin/check-rego-syntax.sh
# Usage: /usr/local/bin/check-rego-syntax.sh policy.rego ```
Rego Syntax Checklist
| Check | Expected |
|---|---|
| Package declaration | First non-comment line |
| Comparison operators | == != < > <= >= |
| Comments | # not // or /* */ |
| Braces matched | {} paired correctly |
| Iteration | some keyword |
| Imports | future.keywords.* |
| Rules | identifier if { } |
| Functions | name(args) if { } |
Verify the Fix
```bash # After fixing Rego syntax errors
# 1. Parse policy opa parse policy.rego // Parse tree output (no errors)
# 2. Check policy opa check policy.rego // No errors
# 3. Evaluate policy opa eval -d policy.rego 'data.package.allow' // Returns result
# 4. Run tests opa test policy.rego -v // Tests pass
# 5. Use in OPA/Gatekeeper // Policy loads successfully ```
Related Issues
- [Fix OPA Policy Evaluation Error](/articles/fix-opa-policy-evaluation-error)
- [Fix OPA Gatekeeper Violation False](/articles/fix-opa-gatekeeper-violation-false)
- [Fix Kubernetes Admission Webhook Failed](/articles/fix-kubernetes-admission-webhook-failed)