@@ -71,6 +71,9 @@ const SHELL_ENV_EXPECTED_KEYS = [
7171 "OPENCLAW_GATEWAY_PASSWORD" ,
7272] ;
7373
74+ const OPEN_DM_POLICY_ALLOW_FROM_RE =
75+ / ^ (?< policyPath > [ a - z 0 - 9 _ . - ] + ) \s * = \s * " o p e n " \s + r e q u i r e s \s + (?< allowPath > [ a - z 0 - 9 _ . - ] + ) (?: \s + \( o r \s + [ a - z 0 - 9 _ . - ] + \) ) ? \s + t o i n c l u d e " \* " $ / i;
76+
7477const CONFIG_AUDIT_LOG_FILENAME = "config-audit.jsonl" ;
7578const loggedInvalidConfigs = new Set < string > ( ) ;
7679
@@ -136,6 +139,27 @@ function hashConfigRaw(raw: string | null): string {
136139 . digest ( "hex" ) ;
137140}
138141
142+ function formatConfigValidationFailure ( pathLabel : string , issueMessage : string ) : string {
143+ const match = issueMessage . match ( OPEN_DM_POLICY_ALLOW_FROM_RE ) ;
144+ const policyPath = match ?. groups ?. policyPath ?. trim ( ) ;
145+ const allowPath = match ?. groups ?. allowPath ?. trim ( ) ;
146+ if ( ! policyPath || ! allowPath ) {
147+ return `Config validation failed: ${ pathLabel } : ${ issueMessage } ` ;
148+ }
149+
150+ return [
151+ `Config validation failed: ${ pathLabel } ` ,
152+ "" ,
153+ `Configuration mismatch: ${ policyPath } is "open", but ${ allowPath } does not include "*".` ,
154+ "" ,
155+ "Fix with:" ,
156+ ` openclaw config set ${ allowPath } '["*"]'` ,
157+ "" ,
158+ "Or switch policy:" ,
159+ ` openclaw config set ${ policyPath } "pairing"` ,
160+ ] . join ( "\n" ) ;
161+ }
162+
139163function isNumericPathSegment ( raw : string ) : boolean {
140164 return / ^ [ 0 - 9 ] + $ / . test ( raw ) ;
141165}
@@ -999,7 +1023,8 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) {
9991023 if ( ! validated . ok ) {
10001024 const issue = validated . issues [ 0 ] ;
10011025 const pathLabel = issue ?. path ? issue . path : "<root>" ;
1002- throw new Error ( `Config validation failed: ${ pathLabel } : ${ issue ?. message ?? "invalid" } ` ) ;
1026+ const issueMessage = issue ?. message ?? "invalid" ;
1027+ throw new Error ( formatConfigValidationFailure ( pathLabel , issueMessage ) ) ;
10031028 }
10041029 if ( validated . warnings . length > 0 ) {
10051030 const details = validated . warnings
0 commit comments