@@ -158,11 +158,11 @@ def emit(self, record, level_id, from_decorator, is_raw, colored_message):
158158 elif self ._is_formatter_dynamic :
159159 if not self ._colorize :
160160 precomputed_format = self ._memoize_dynamic_format (dynamic_format )
161- formatted = precomputed_format . format_map ( formatter_record )
161+ formatted = self . _format_record ( precomputed_format , formatter_record )
162162 elif colored_message is None :
163163 ansi_level = self ._levels_ansi_codes [level_id ]
164164 _ , precomputed_format = self ._memoize_dynamic_format (dynamic_format , ansi_level )
165- formatted = precomputed_format . format_map ( formatter_record )
165+ formatted = self . _format_record ( precomputed_format , formatter_record )
166166 else :
167167 ansi_level = self ._levels_ansi_codes [level_id ]
168168 formatter , precomputed_format = self ._memoize_dynamic_format (
@@ -172,24 +172,24 @@ def emit(self, record, level_id, from_decorator, is_raw, colored_message):
172172 record ["message" ], ansi_level = ansi_level , colored_message = colored_message
173173 )
174174 formatter_record ["message" ] = coloring_message
175- formatted = precomputed_format . format_map ( formatter_record )
175+ formatted = self . _format_record ( precomputed_format , formatter_record )
176176
177177 else :
178178 if not self ._colorize :
179179 precomputed_format = self ._decolorized_format
180- formatted = precomputed_format . format_map ( formatter_record )
180+ formatted = self . _format_record ( precomputed_format , formatter_record )
181181 elif colored_message is None :
182182 ansi_level = self ._levels_ansi_codes [level_id ]
183183 precomputed_format = self ._precolorized_formats [level_id ]
184- formatted = precomputed_format . format_map ( formatter_record )
184+ formatted = self . _format_record ( precomputed_format , formatter_record )
185185 else :
186186 ansi_level = self ._levels_ansi_codes [level_id ]
187187 precomputed_format = self ._precolorized_formats [level_id ]
188188 coloring_message = self ._formatter .make_coloring_message (
189189 record ["message" ], ansi_level = ansi_level , colored_message = colored_message
190190 )
191191 formatter_record ["message" ] = coloring_message
192- formatted = precomputed_format . format_map ( formatter_record )
192+ formatted = self . _format_record ( precomputed_format , formatter_record )
193193
194194 if self ._serialize :
195195 formatted = self ._serialize_record (formatted , record )
@@ -204,10 +204,6 @@ def emit(self, record, level_id, from_decorator, is_raw, colored_message):
204204 self ._queue .put (str_record )
205205 else :
206206 self ._sink .write (str_record )
207- except KeyError as e :
208- if not self ._error_interceptor .should_catch ():
209- raise self ._make_key_error (e , record ) from e
210- self ._error_interceptor .print (record , exception = self ._make_key_error (e , record ))
211207 except Exception :
212208 if not self ._error_interceptor .should_catch ():
213209 raise
@@ -248,22 +244,25 @@ def update_format(self, level_id):
248244 ansi_code = self ._levels_ansi_codes [level_id ]
249245 self ._precolorized_formats [level_id ] = self ._formatter .colorize (ansi_code )
250246
251- @staticmethod
252- def _make_key_error (original , record ):
253- key = original .args [0 ] if original .args else "?"
254- available = ", " .join (sorted (record .keys ()))
255- message = (
256- "The format string references an unknown key '%s'. "
257- "Available record keys are: %s. "
258- "To include custom data, use 'logger.bind(key=value)' and reference it "
259- "as '{extra[key]}' in the format string." % (key , available )
260- )
261- return KeyError (message )
262-
263247 @property
264248 def levelno (self ):
265249 return self ._levelno
266250
251+ @staticmethod
252+ def _format_record (log_format , record ):
253+ try :
254+ return log_format .format_map (record )
255+ except KeyError as e :
256+ available = ", " .join (map (repr , record .keys ()))
257+ raise ValueError (
258+ "Failed to format log record: key %s not found.\n "
259+ "Verify that the format string %r only references valid record keys "
260+ "and that all required extra keys are present.\n "
261+ "Available records key are: %s.\n "
262+ "To include custom data, use `logger.bind(key=value)` and reference it "
263+ "as '{extra[key]}' in the format string." % (e , log_format , available )
264+ ) from e
265+
267266 @staticmethod
268267 def _serialize_record (text , record ):
269268 exception = record ["exception" ]
0 commit comments