summaryrefslogtreecommitdiff
path: root/doc/build/errors.rst
Commit message (Collapse)AuthorAgeFilesLines
* disallow adding to identity map that's been discardedMike Bayer2021-10-041-0/+79
| | | | | | | | | | | | | | | | Fixed bug where iterating a :class:`.Result` from a :class:`_orm.Session` after that :class:`_orm.Session` were closed would partially attach objects to that session in an essentially invalid state. It now raises an exception with a link to new documentation if an **un-buffered** result is iterated from a :class:`_orm.Session` that was closed or otherwise had the :meth:`_orm.Session.expunge_all` method called after that :class:`.Result` was generated. The "prebuffer_rows" execution option, as is used by the asyncio extension, may be used to produce a :class:`.Result` where the ORM objects are prebuffered, and in this case iterating the result will produce a series of detached objects. Fixes: #7128 Change-Id: I59f0ae32a83a64587937741b80f31ff825bbb574
* warn or deprecate for auto-aliasing in joinsMike Bayer2021-09-281-0/+176
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | An extra layer of warning messages has been added to the functionality of :meth:`_orm.Query.join` and the ORM version of :meth:`_sql.Select.join`, where a few places where "automatic aliasing" continues to occur will now be called out as a pattern to avoid, mostly specific to the area of joined table inheritance where classes that share common base tables are being joined together without using explicit aliases. One case emits a legacy warning for a pattern that's not recommended, the other case is fully deprecated. The automatic aliasing within ORM join() which occurs for overlapping mapped tables does not work consistently with all APIs such as ``contains_eager()``, and rather than continue to try to make these use cases work everywhere, replacing with a more user-explicit pattern is clearer, less prone to bugs and simplifies SQLAlchemy's internals further. The warnings include links to the errors.rst page where each pattern is demonstrated along with the recommended pattern to fix. * Improved the exception message generated when configuring a mapping with joined table inheritance where the two tables either have no foreign key relationships set up, or where they have multiple foreign key relationships set up. The message is now ORM specific and includes context that the :paramref:`_orm.Mapper.inherit_condition` parameter may be needed particularly for the ambiguous foreign keys case. * Add explicit support in the _expect_warnings() assertion for nested _expect_warnings calls * generalize the NoCache fixture, which we also need to catch warnings during compilation consistently * generalize the __str__() method for the HasCode mixin so all warnings and errors include the code link in their string Fixes: #6974 Change-Id: I84ed79ba2112c39eaab7973b6d6f46de7fa80842
* fix: typos in doc/build/core and doc/build/errors (#7006)Kevin Kirsche2021-09-081-2/+2
|
* Improve error message when inspecting async proxiesFederico Caselli2021-08-301-0/+28
| | | | | | | Provide better error message when trying to insepct and async engine or asnyc connection. Change-Id: I907f3a22c6b76fe43df9d40cb0e69c57f74a7982
* standardizing docs #6821jonathan vanasco2021-08-231-5/+5
| | | | | | | | | | | | | | | | | | | | | | | | | (redo of 2999/I5609025feee8cfdecc09b55bfbf1bd13fa2e6602) This PR is designed to bring more clarity within the docs by renaming object instances that may be consfusingly similar to class, method, and attribute names. For example, instances of the class `MetaData` are available on some objects as `.metadata` property, and had appeared within the docs as both `meta` and `metadata` which has confused some users in the past. By this PR, the docs now utilize the following naming convention: * MetaData - SQLAlchemy class * .metadata - SQLAlchemy API attributes * metadata_obj - developer instantiated metadata objects or references Detailed Changes: * standardized `meta` and `metadata` instances to `metadata_obj`. note: the docs were evenly split between 'meta' and 'metadata'. * standardized 'cursor' to 'cursor_obj' to avoid confusion with the method. * standardized a 'scalar_subquery = ' to 'scalar_subq' to avoid confusion with the method. * standardized a 'cte = ' to 'cte_obj' to avoid confusion with the method Change-Id: I79c98aee16c5fc6649289b2dd7d6dfc368222fb4
* improve "overlaps" warning; test for m2mMike Bayer2021-06-011-4/+12
| | | | | | | | | | | The warning that's emitted for :func:`_orm.relationship` when multiple relationships would overlap with each other as far as foreign key attributes written towards, now includes the specific "overlaps" argument to use for each warning in order to silence the warning without changing the mapping. Fixes: #6400 Change-Id: I43c04f8018dda4e0f83ae58b8c7fd95084d9e95d
* Merge "docs: fix back_populates parameter reference"mike bayer2021-05-181-1/+1
|\
| * docs: fix back_populates parameter referenceMaico Timmerman2021-05-061-1/+1
| | | | | | | | | | | | Fixes reference to relationship.back_populates in errors.rst. Change-Id: I60ac97d5adcf453aa8363266210ceda4688baa6d
* | Improve cascade backrefs warning and add `code` to deprecation warningsStephen Rosen2021-05-101-0/+32
|/ | | | | | | | | | | | This adds a new description to errors.rst and adds support for any SQLAlchemy warning to refer to an errors.rst code. Fixes: #6148 Closes: #6250 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/6250 Pull-request-sha: dbcaeb54e31517fe88f6f8c515f1024002675f13 Change-Id: I4303c62ac9b1f13f67a34f825687014f1771c98c
* Expand sibling tests for overlaps warningMike Bayer2021-03-311-0/+77
| | | | | | | | | | | | | Scaled back the warning message added in :ticket:`5171` to not warn for overlapping columns in an inheritance scenario where a particular relationship is local to a subclass and therefore does not represent an overlap. Add errors documentation for the warning and also expand ``util.warn()`` to include a code parameter. Fixes: #6171 Change-Id: Icb1f12d8d645d439ffd2bbb7371c6b00042b6ae3
* link to the asyncio ORM section for this issueMike Bayer2021-03-301-7/+7
| | | | | Change-Id: I1ef2230a1b1b77b55f3d835754836ca1bd023172 references: #6164
* Improve error message when await_ call errorsFederico Caselli2021-01-211-1/+17
| | | | | Fixes: #5832 Change-Id: Ia2ed8f1d1ec54e5f6e1a8f817a69446fdb3b7f6d
* Major revisals to lambdasMike Bayer2020-12-161-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 1. Improve coercions._deep_is_literal to check sequences for clause elements, thus allowing a phrase like lambda: col.in_([literal("x"), literal("y")]) to be handled 2. revise closure variable caching completely. All variables entering must be part of a closure cache key or rejected. only objects that can be resolved to HasCacheKey or FunctionType are accepted; all other types are rejected. This adds a high degree of strictness to lambdas and will make them a little more awkward to use in some cases, however prevents several classes of critical issues: a. previously, a lambda that had an expression derived from some kind of state, like "self.x", or "execution_context.session.foo" would produce a closure cache key from "self" or "execution_context", objects that can very well be per-execution and would therefore cause a AnalyzedFunction objects to overflow. (memory won't leak as it looks like an LRUCache is already used for these) b. a lambda, such as one used within DeferredLamdaElement, that produces different SQL expressions based on the arguments (which is in fact what it's supposed to do), however it would through the use of conditionals produce different bound parameter combinations, leading to literal parameters not tracked properly. These are now rejected as uncacheable whereas previously they would again be part of the closure cache key, causing an overflow of AnalyizedFunction objects. 3. Ensure non-mapped mixins are handled correctly by with_loader_criteria(). 4. Fixed bug in lambda SQL system where we are not supposed to allow a Python function to be embedded in the lambda, since we can't predict a bound value from it. While there was an error condition added for this, it was not tested and wasn't working; an informative error is now raised. 5. new docs for lambdas 6. consolidated changelog for all of these Fixes: #5760 Fixes: #5765 Fixes: #5766 Fixes: #5768 Fixes: #5770 Change-Id: Iedaa636c3225fad496df23b612c516c8ab247ab7
* Detect non compatible execution in async modeFederico Caselli2020-12-081-0/+18
| | | | | | | | | | The SQLAlchemy async mode now detects and raises an informative error when an non asyncio compatible :term:`DBAPI` is used. Using a standard ``DBAPI`` with async SQLAlchemy will cause it to block like any sync call, interrupting the executing asyncio loop. Change-Id: I9aed87dc1b0df53e8cb2109495237038aa2cb2d4
* tutorial 2.0 WIPreview/mike_bayer/tutorial20Mike Bayer2020-10-311-1/+1
| | | | | | | | | | | | | | Add SelectBase.exists() method as it seems strange this is not available already. The Exists construct itself does not provide full SELECT-building capabilities so it makes sense this should be used more like a scalar_subquery. Make sure stream_results is getting set up when yield_per is used, for 2.0 style statements as well. this was hardcoded inside of Query.yield_per() and is now moved to take place within QueryContext. Change-Id: Icafcd4fd9b708772343d56edf40995c9e8f835d6
* added docstring about expire_on_commit for #5243jonathan vanasco2020-10-261-3/+13
| | | | | | | | | Fixes: #5243 Closes: #5328 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/5328 Pull-request-sha: e760ed4ef1749aadfb8d63d776c764d98b93b1e5 Change-Id: I8e7bc3429dc279d447cc66400c76b4d2a04626aa
* new docs WIPMike Bayer2020-09-241-3/+8
| | | | | | | | | | | | | | | This WIP is part of the final push for 1.4's docs to fully "2.0-ize" what we can, and have it all ready. So far this includes a rewrite of the 2.0 migration, set up for the 1.4 /2.0 docs style, and a total redesign of the index page using a new flex layout in zzzeeksphinx. It also reworks some of the API reference sections to have more subheaders. zzzeeksphinx is also enhanced to provide automatic summaries for all api doc section. Change-Id: I01d360cb9c8749520246b96ee6496143c6037918
* Update select usage to use the new 1.4 formatFederico Caselli2020-09-081-7/+7
| | | | | | | | | | | | | | | | This change includes mainly that the bracketed use within select() is moved to positional, and keyword arguments are removed from calls to the select() function. it does not yet fully address other issues such as keyword arguments passed to the table.select(). Additionally, allows False / None to both be considered as "disable" for all of select.correlate(), select.correlate_except(), query.correlate(), which establishes consistency with passing of ``False`` for the legact select(correlate=False) argument. Change-Id: Ie6c6e6abfbd3d75d4c8de504c0cf0159e6999108
* Emit v2.0 deprecation warning for "implicit autocommit"Gord Thompson2020-08-281-7/+6
| | | | | | | | | | | | | | | | | | | | | | | | | "Implicit autocommit", which is the COMMIT that occurs when a DML or DDL statement is emitted on a connection, is deprecated and won't be part of SQLAlchemy 2.0. A 2.0-style warning is emitted when autocommit takes effect, so that the calling code may be adjusted to use an explicit transaction. As part of this change, DDL methods such as :meth:`_schema.MetaData.create_all` when used against a :class:`_engine.Engine` or :class:`_engine.Connection` will run the operation in a BEGIN block if one is not started already. The MySQL and MariaDB dialects now query from the information_schema.tables system view in order to determine if a particular table exists or not. Previously, the "DESCRIBE" command was used with an exception catch to detect non-existent, which would have the undesirable effect of emitting a ROLLBACK on the connection. There appeared to be legacy encoding issues which prevented the use of "SHOW TABLES", for this, but as MySQL support is now at 5.0.2 or above due to :ticket:`4189`, the information_schema tables are now available in all cases. Fixes: #4846 Change-Id: I733a7e0e17477a63607fb9931c87c393bbd7ac57
* Fix typosKarthikeyan Singaravelan2020-08-091-2/+2
|
* Establish future behavior for Session cascade backrefs, bindMike Bayer2020-08-011-0/+49
| | | | | | | | | | | | | | | | | | | | The behavior of the :paramref:`_orm.relationship.cascade_backrefs` flag will be reversed in 2.0 and set to ``False`` unconditionally, such that backrefs don't cascade save-update operations from a forwards-assignment to a backwards assignment. A 2.0 deprecation warning is emitted when the parameter is left at its default of ``True`` at the point at which such a cascade operation actually takes place. The new behavior can be established as always by setting the flag to ``False`` on a specific :func:`_orm.relationship`, or more generally can be set up across the board by setting the the :paramref:`_orm.Session.future` flag to True. Additionally in the interests of expediency, this commit will also move Session away from making use of bound metadata if the future=True flag is set. An application that sets future=True should ideally have to change as little else as possible for full 2.0 behavior. Fixes: #5150 Change-Id: I490d1d61f09c62ffc2de983208aeed25dfe48aec
* Add future=True to create_engine/Session; unify select()Mike Bayer2020-07-081-1/+50
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Several weeks of using the future_select() construct has led to the proposal there be just one select() construct again which features the new join() method, and otherwise accepts both the 1.x and 2.x argument styles. This would make migration simpler and reduce confusion. However, confusion may be increased by the fact that select().join() is different Current thinking is we may be better off with a few hard behavioral changes to old and relatively unknown APIs rather than trying to play both sides within two extremely similar but subtly different APIs. At the moment, the .join() thing seems to be the only behavioral change that occurs without the user taking any explicit steps. Session.execute() will still behave the old way as we are adding a future flag. This change also adds the "future" flag to Session() and session.execute(), so that interpretation of the incoming statement, as well as that the new style result is returned, does not occur for existing applications unless they add the use of this flag. The change in general is moving the "removed in 2.0" system further along where we want the test suite to fully pass even if the SQLALCHEMY_WARN_20 flag is set. Get many tests to pass when SQLALCHEMY_WARN_20 is set; this should be ongoing after this patch merges. Improve the RemovedIn20 warning; these are all deprecated "since" 1.4, so ensure that's what the messages read. Make sure the inforamtion link is on all warnings. Add deprecation warnings for parameters present and add warnings to all FromClause.select() types of methods. Fixes: #5379 Fixes: #5284 Change-Id: I765a0b912b3dcd0e995426427d8bb7997cbffd51 References: #5159
* Merge "Update transaction / connection handling"mike bayer2020-05-171-20/+42
|\
| * Update transaction / connection handlingMike Bayer2020-05-171-20/+42
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | step one, do away with __connection attribute and using awkward AttributeError logic step two, move all management of "connection._transaction" into the transaction objects themselves where it's easier to follow. build MarkerTransaction that takes the role of "do-nothing block" new connection datamodel is: connection._transaction, always a root, connection._nested_transaction, always a nested. nested transactions still chain to each other as this is still sort of necessary but they consider the root transaction separately, and the marker transactions not at all. introduce new InvalidRequestError subclass PendingRollbackError. Apply to connection and session for all cases where a transaction needs to be rolled back before continuing. Within Connection, both PendingRollbackError as well as ResourceClosedError are now raised directly without being handled by handle_dbapi_error(); this removes these two exception cases from the handle_error event handler as well as from StatementError wrapping, as these two exceptions are not statement oriented and are instead programmatic issues, that the application is failing to handle database errors properly. Revise savepoints so that when a release fails, they set themselves as inactive so that their rollback() method does not throw another exception. Give savepoints another go on MySQL, can't get release working however get support for basic round trip going Fixes: #5327 Change-Id: Ia3cbbf56d4882fcc7980f90519412f1711fae74d
* | Reword delete-orphan on many error message and documentMike Bayer2020-05-161-0/+221
|/ | | | | | | | | | | | | | For many years we have encountered users making use of the "single_parent" flag in response to the error message for "delete-orphan" expressing this as a means to cancel the current error. However, the actual issue here is usually a misuse of the delete-orphan cascade setting. Reword the error message to be much more descriptive about what this means and add new error link sections describing the situation in as much detail as possible. Fixes: #5329 Change-Id: I7ba710378b2935479ab22ff9a0a79c692dbf69a6
* Set up absolute references for create_engine and relatedMike Bayer2020-04-141-4/+4
| | | | | | | includes more replacements for create_engine(), Connection, disambiguation of Result from future/baked Change-Id: Icb60a79ee7a6c45ea9056c211ffd1be110da3b5e
* Run search and replace of symbolic module namesMike Bayer2020-04-141-29/+29
| | | | | | | | Replaces a wide array of Sphinx-relative doc references with an abbreviated absolute form now supported by zzzeeksphinx. Change-Id: I94bffcc3f37885ffdde6238767224296339698a2
* Enable zzzeeksphinx module prefixesMike Bayer2020-04-141-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | zzzeeksphinx 1.1.2 in git can now convert short prefix names in a configured lookup to fully qualified module names, so that we can have succinct and portable pyrefs that still resolve absolutely. It also includes a formatter that will format all pyrefs in a fully consistent way regardless of the package path, by unconditionally removing all package tokens but always leaving class names in place including for methods, which means we no longer have to deal with tildes in pyrefs. The most immediate goal of the absolute prefixes is that we have lots of "ambiguous" names that appear in muliple places, like select(), ARRAY, ENUM etc. With the incoming future packages there is going to be lots of name overlap so it is necessary that all names eventually use absolute package paths when Sphinx receives them. In multiple stages, pyrefs will be converted using the zzzeeksphinx tools/fix_xrefs.py tool so that doclinks can be made absolute using symbolic prefixes. For this review, the actual search and replace of symbols is not performed, instead some general cleanup to prepare the docs as well as a lookup file used by the tool to do the conversion. this relatively small patch will be backported with appropriate changes to 1.3, 1.2, 1.1 and the tool can then be run on each branch individually. We are shooting for almost no warnings at all for master (still a handful I can't figure out which don't seem to have any impact) , very few for 1.3, and for 1.2 / 1.1 we hope for a significant reduction in warnings. Overall for all versions pyrefs should always point to the correct target, if they are in fact hyperlinked. it's better for a ref to go nowhere and be plain text than go to the wrong thing. Right now, hundreds of API links are pointing to the wrong thing as they are ambiguous names such as refresh(), insert(), update(), select(), join(), JSON etc. and Sphinx sends these all to essesntially random destinations among as many as five or six possible choices per symbol. A shorthand system that allows us to use absolute refs without having to type out a full blown absoulte module is the only way this is going to work, and we should ultimately seek to abandon any use of prefix dot for lookups. Everything should be on an underscore token so at the very least the module spaces can be reorganized without having to search and replace the entire documentation every time. Change-Id: I484a7329034af275fcdb322b62b6255dfeea9151
* Change ``orm.future`` to ``future.orm``Federico Caselli2020-04-081-1/+1
| | | | Change-Id: I7fcf8b691134a0c52fbbf7879da071a41ec28102
* Correct ambiguous func / class linksMike Bayer2020-03-251-1/+1
| | | | | | | | | :func:`.sql.expression.select`, :func:`.sql.expression.insert` and :class:`.sql.expression.Insert` were hitting many ambiguous symbol errors, due to future.select, as well as the PG/MySQL variants of Insert. Change-Id: Iac862bfc172a7f7f0cbba5353a83dc203bed376c
* Deprecate plain string in execute and introduce `exec_driver_sql`Federico Caselli2020-03-211-1/+1
| | | | | | | | | | | | | | | Execution of literal sql string is deprecated in the :meth:`.Connection.execute` and a warning is raised when used stating that it will be coerced to :func:`.text` in a future release. To execute a raw sql string the new connection method :meth:`.Connection.exec_driver_sql` was added, that will retain the previous behavior, passing the string to the DBAPI driver unchanged. Usage of scalar or tuple positional parameters in :meth:`.Connection.execute` is also deprecated. Fixes: #4848 Fixes: #5178 Change-Id: I2830181054327996d594f7f0d59c157d477c3aa9
* Create initial future package, RemovedIn20WarningMike Bayer2020-02-121-0/+37
| | | | | | | | | | | | | | | | | Reorganization of Select() is the first major element of the 2.0 restructuring. In order to start this we need to first create the new Select constructor and apply legacy elements to the old one. This in turn necessitates starting up the RemovedIn20Warning concept which itself need to refer to "sqlalchemy.future", so begin to establish this basic framework. Additionally, update the DML constructors with the newer no-keyword style. Remove the use of the "pending deprecation" and fix Query.add_column() deprecation which was not acting as deprecated. Fixes: #4845 Fixes: #4648 Change-Id: I0c7a22b2841a985e1c379a0bb6c94089aae6264c
* Fix typo in docs (errors.rst)Mikhail Burshteyn2019-09-181-1/+1
|
* SelectBase no longer a FromClauseMike Bayer2019-07-061-1/+56
| | | | | | | | | | | | | | | | | | | | As part of the SQLAlchemy 2.0 migration project, a conceptual change has been made to the role of the :class:`.SelectBase` class hierarchy, which is the root of all "SELECT" statement constructs, in that they no longer serve directly as FROM clauses, that is, they no longer subclass :class:`.FromClause`. For end users, the change mostly means that any placement of a :func:`.select` construct in the FROM clause of another :func:`.select` requires first that it be wrapped in a subquery first, which historically is through the use of the :meth:`.SelectBase.alias` method, and is now also available through the use of :meth:`.SelectBase.subquery`. This was usually a requirement in any case since several databases don't accept unnamed SELECT subqueries in their FROM clause in any case. See the documentation in this change for lots more detail. Fixes: #4617 Change-Id: I0f6174ee24b9a1a4529168e52e855e12abd60667
* Don't discard inactive transaction until it is explicitly rolled backMike Bayer2019-06-101-0/+42
| | | | | | | | | | | | | | | | | The :class:`.Connection` object will now not clear a rolled-back transaction until the outermost transaction is explicitly rolled back. This is essentially the same behavior that the ORM :class:`.Session` has had for a long time, where an explicit call to ``.rollback()`` on all enclosing transactions is required for the transaction to logically clear, even though the DBAPI-level transaction has already been rolled back. The new behavior helps with situations such as the "ORM rollback test suite" pattern where the test suite rolls the transaction back within the ORM scope, but the test harness which seeks to control the scope of the transaction externally does not expect a new transaction to start implicitly. Fixes: #4712 Change-Id: Ibc6c8d981cff31594a5d26dd5203fd9cfcea1c74
* Rework Session transaction FAQsMike Bayer2019-06-071-0/+19
| | | | | | | | | | | | | | In preparation for #4712, add an errors.rst code to the Session's exception about waiting to be rolled back and rework the FAQ entry to be much more succinct. When this FAQ was first written, I found it hard to describe why flush worked this way but as the use case is clearer now, and #4712 actually showed it being confusing when it doesn't work this way, we can make a simpler and more definitive statement about this behavior. Additionally, language about "subtransactions" is minimized as I might be removing or de-emphasizing this concept in 2.0 (though maybe not as it does seem to work well). Change-Id: I557872aff255b07e14dd843aa024e027a017afb8
* Enhance documentation for string compilation use casesMike Bayer2019-04-041-0/+71
| | | | | | | | | | - Add a web link for UnsupportedCompilationError - Add new section to errors.rst - add more detail and cross-linking to the FAQ - include security caveats for parameter rendering Fixes: #4595 Change-Id: I31ea57c18d65770cd2a51276bbe2847a9eb72bba
* Fix many spell glitchesLele Gaifax2019-01-251-1/+1
| | | | | | | | | | | | This affects mostly docstrings, except in orm/events.py::dispose_collection() where one parameter gets renamed: given that the method is empty, it seemed reasonable to me to fix that too. Closes: #4440 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/4440 Pull-request-sha: 779ed75acb6142e1f1daac467b5b14134529bb4b Change-Id: Ic0553fe97853054b09c2453af76d96363de6eb0e
* Add __clause_element__ to ColumnPropertyMike Bayer2018-11-271-0/+44
| | | | | | | | | | | | Added a ``__clause_element__()`` method to :class:`.ColumnProperty` which can allow the usage of a not-fully-declared column or deferred attribute in a declarative mapped class slightly more friendly when it's used in a constraint or other column-oriented scenario within the class declaration, though this still can't work in open-ended expressions; prefer to call the :attr:`.ColumnProperty.expression` attribute if receiving ``TypeError``. Fixes: #4372 Change-Id: I5d3d1adb9c77de0566298bc2c46e9001d314b0c7
* Add new errors sectionMike Bayer2017-12-221-0/+506
Adding this to master so that it can be published, in advance of the exception-level site integration feature. Change-Id: Ia2a61df8e5198b81ef8f5fbac91143767b70c26b