This page contains information about the purpose and use of all index events.
Subscribing to events
The events of an index are available through the events property of the Index class, which returns an EventHub object. A handler is a function, a lambda or another callable that takes two arguments: the sender and the event arguments. Subscribe a handler with +=, for example index.events.file_indexing += on_file_indexing; -= removes the subscription made last with the handler, and clear() removes all the handlers of the event, for example index.events.file_indexing.clear().
A handler runs on the thread that raises the event:
During a synchronous operation with one indexing thread (the default), the events are raised on the thread that called the method, for example, the method add.
During an asynchronous operation (IndexingOptions.is_async is True), the method returns before the operation completes, and the events that follow are raised on engine worker threads. Wait for the operation_finished event, for example with a threading.Event, before the script uses the results or ends.
An exception that a handler raises on the calling thread reaches the engine: for example, an exception raised by a file_indexing handler is reported by the error_occurred event, and the document is not indexed. An exception raised on an engine worker thread is printed to stderr and ignored.
OPTIMIZING - optimizing an index (merging its segments);
DELETING - deleting documents from an index by paths or by document keys.
This event can be used to receive notification of the completion of an asynchronous operation. In the following example, the add method returns at once, and the event is raised on an engine worker thread; the script waits for it with a threading.Event.
importthreadingfromgroupdocs.searchimportIndexfromgroupdocs.search.optionsimportIndexingOptions# Creating an indexindex=Index("./index")finished=threading.Event()# Subscribing to the eventdefon_operation_finished(sender,args):# Writing operation details to the consoleprint("Operation finished:",args.operation_type.name)print("Message:",args.message)print("Index folder:",args.index_folder)print("Time:",args.time)finished.set()index.events.operation_finished+=on_operation_finished# Indexing documents from the specified folderoptions=IndexingOptions()options.is_async=True# Enabling asynchronous indexing modeindex.add("./documents",options)# The method returns before the operation completes, so waiting for the eventfinished.wait()
Operation finished: INDEXING
Message: Files has been added to Index e180c83d-2c46-4cff-b4d6-8be087de3682.
Index folder: index
Time: 2026-10-29 19:04:58.548210+02:00
The error_occurred event occurs when an error happens in an index. Errors in an index can be caused, for example, by file system errors or unsupported formats of indexed documents. The is_critical property of the event arguments indicates a critical error after which the index gets the FAILED status and has to be opened again. The check_segments method also reports the damage found and the repairs made through this event (see Checking index integrity). An example of receiving error notifications in the index is presented below.
fromgroupdocs.searchimportIndex# Creating an indexindex=Index("./index")# Subscribing to the eventdefon_error_occurred(sender,args):# Writing an error message to the consoleprint(("Critical error: "ifargs.is_criticalelse"Error: ")+args.message)index.events.error_occurred+=on_error_occurred# Indexing documents from the specified folderindex.add("./documents")# Searching in the indexresult=index.search("Einstein")print("Documents found:",result.document_count)
Error: Error during text extraction from documents\damaged.pdf
GroupDocs.Parser.Exceptions.UnsupportedDocumentFormatException: Exception of type 'GroupDocs.Parser.Exceptions.UnsupportedDocumentFormatException' was thrown.
at .(Stream , LoadOptions )
at .()
at GroupDocs.Parser.Parser.GetMetadata()
at .()
at .(Document , , String )
Error: Error during text extraction from documents\protected.pdf
GroupDocs.Parser.Exceptions.InvalidPasswordExc
[TRUNCATED]
The operation_progress_changed event occurs when the progress of an indexing or updating operation changes. The event arguments (OperationProgressEventArgs) contain the total number of documents to process, the numbers of processed and skipped documents, the progress percentage, as well as the key, the path and the status of the last processed document. The example below demonstrates how to track the progress of an index operation.
fromgroupdocs.searchimportIndex# Creating an indexindex=Index("./index")# Subscribing to the eventdefon_operation_progress_changed(sender,args):print("Last processed:",args.last_document_path)print("Result:",args.last_document_status.name)print("Processed documents:",args.processed_documents)print("Skipped documents:",args.skipped_documents)print("Total documents:",args.total_documents)print("Progress percentage:",args.progress_percentage)index.events.operation_progress_changed+=on_operation_progress_changed# Indexing documents from the specified folderindex.add("./documents")
The optimization_progress_changed event occurs when the progress of an index optimization operation changes. The example below demonstrates how to track the progress of the index optimization operation. Each call of the add method creates at least one new segment in the index, so the example adds the documents one by one before optimizing the index.
fromgroupdocs.searchimportIndex# Creating an index and adding documents in separate operations, which creates several segmentsindex=Index("./index")index.add("./documents/einstein-notes.txt")index.add("./documents/newton.txt")index.add("./documents/curie.txt")# Subscribing to the eventdefon_optimization_progress_changed(sender,args):print("Processed segments:",args.processed_segments)print("Total segments:",args.total_segments)print("Progress percentage:",args.progress_percentage)index.events.optimization_progress_changed+=on_optimization_progress_changed# Optimizing the indexindex.optimize()
The password_required event occurs when an index requires a password to open a document. The event is raised before a document is opened, also for a document that is not protected, so the handler sets a password only for the documents that need it. An example of processing this event is presented below.
fromgroupdocs.searchimportIndex# Creating an indexindex=Index("./index")# Subscribing to the eventdefon_password_required(sender,args):ifargs.document_full_path.lower().endswith("protected.pdf"):args.password="123456"print("Password supplied for:",args.document_full_path)index.events.password_required+=on_password_required# Indexing documents from the specified folderindex.add("./documents")# Searching for a word of the protected documentresult=index.search("confidential")print("Documents found:",result.document_count)
The following example demonstrates how to add an additional field to documents whose names end in “report.pdf” and how to skip indexing documents containing “important” text in their paths. The search at the end finds the documents by the added field.
fromgroupdocs.searchimportIndexfromgroupdocs.search.commonimportDocumentField# Creating an indexindex=Index("./index")# Subscribing to the eventdefon_file_indexing(sender,args):path=args.document_full_path.lower()ifpath.endswith("report.pdf"):args.additional_fields=[DocumentField("Tags","Report")]print("Tagged:",args.document_full_path)if"important"inpath:args.skip_indexing=Trueprint("Skipped:",args.document_full_path)index.events.file_indexing+=on_file_indexing# Indexing documents from the specified folderindex.add("./documents")# Searching in the added fieldresult=index.search("Tags:Report")print("Documents found:",result.document_count)
The status_changed event occurs when an index status changes. The new status is available in the status property of the event arguments. The following example demonstrates how to use this event to notify the completion of an index operation. The operation is asynchronous, so the handler receives the final status on an engine worker thread, and the script waits for the notification.
importthreadingfromgroupdocs.searchimportIndexfromgroupdocs.search.commonimportIndexStatusfromgroupdocs.search.optionsimportIndexingOptions# Creating an indexindex=Index("./index")completed=threading.Event()# Subscribing to the eventdefon_status_changed(sender,args):ifargs.status==IndexStatus.READYorargs.status==IndexStatus.FAILED:# A notification of the operation completionprint("The operation is completed. Index status:",args.status.name)completed.set()index.events.status_changed+=on_status_changed# Setting the flag for asynchronous indexingoptions=IndexingOptions()options.is_async=True# Asynchronous indexing documents from the specified folder# The method terminates before the operation completesindex.add("./documents",options)# Waiting for the notificationcompleted.wait()
The search_phase_completed event occurs when a phase (or stage) of a search operation in an index completes. This event is used to study intermediate search results when tuning search queries. Information on the phases of different types of search is presented on the page Search flow. The following example demonstrates the use of this event.
fromgroupdocs.searchimportIndexfromgroupdocs.search.optionsimportSearchOptions# Creating an indexindex=Index("./index")# Indexing documents from the specified folderindex.add("./documents")# Subscribing to the eventdefon_search_phase_completed(sender,args):words=args.wordsprint("Search phase:",args.search_phase.name)print("Words:",len(words))forwordinwords:print("\t"+word)print()index.events.search_phase_completed+=on_search_phase_completedoptions=SearchOptions()options.use_synonym_search=Trueoptions.use_word_forms_search=Trueoptions.fuzzy_search.enabled=Trueoptions.use_homophone_search=Trueresult=index.search("Einstein",options)
The image_preparing event occurs immediately before adding indexed image to an index. The event can be used, for example, to save an image separately from its containing document, since it provides an image data stream (image_stream).
The event is raised for every separate image file, whether or not image indexing is enabled. When enabled_for_separate_images is False, the image is not indexed and image_frames is empty. For an image embedded in a document, the event is raised only when enabled_for_embedded_images is True.
The following example demonstrates the use of this event. It enables the image indexing options, which index images for reverse image search.
fromgroupdocs.searchimportIndexfromgroupdocs.search.optionsimportIndexingOptions# Creating an indexindex=Index("./index")# Subscribing to the eventdefon_image_preparing(sender,args):print("Document:",args.document_key)print("Image inner path:","/".join(args.inner_path))print("Image index:",args.image_index)print("Image frames:",len(args.image_frames))index.events.image_preparing+=on_image_preparing# Indexing images of separate image files and images embedded in documentsoptions=IndexingOptions()options.image_indexing_options.enabled_for_separate_images=Trueoptions.image_indexing_options.enabled_for_embedded_images=True# Indexing filesindex.add("./documents",options)